home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 2007 December / PCWKCD1207B.iso / Blogowanie poza sfera / Flock 0.9.1.3 stable / flock-0.9.1.3.en-US.win32.exe / flock / chrome / browser.jar / content / browser / bookmarks / bookmarks.js < prev    next >
Text File  |  2007-08-02  |  97KB  |  2,663 lines

  1. //@line 39 "/cygdrive/K/tinderbuild/src/flock/mozilla/browser/components/bookmarks/content/bookmarks.js"
  2.  
  3. //@line 43 "/cygdrive/K/tinderbuild/src/flock/mozilla/browser/components/bookmarks/content/bookmarks.js"
  4. const ADD_BM_DIALOG_FEATURES = "centerscreen,chrome,dialog,resizable,dependent";
  5. //@line 45 "/cygdrive/K/tinderbuild/src/flock/mozilla/browser/components/bookmarks/content/bookmarks.js"
  6.  
  7. const kBATCH_LIMIT = 4;
  8.  
  9. var gNC_NS, gWEB_NS, gRDF_NS, gXUL_NS, gNC_NS_CMD;
  10.  
  11. // definition of the services frequently used for bookmarks
  12. var kRDFContractID;
  13. var kRDFSVCIID;
  14. var kRDFRSCIID;
  15. var kRDFLITIID;
  16. var RDF;
  17.  
  18. var kRDFCContractID;
  19. var kRDFCIID;
  20. var RDFC;
  21.  
  22. var kRDFCUContractID;
  23. var kRDFCUIID;
  24. var RDFCU;
  25.  
  26. var BMDS;
  27. var kBMSVCIID;
  28. var kFFSVCIID;
  29. var BMSVC;
  30. var FFSVC;
  31.  
  32. var kPREFContractID;
  33. var kPREFIID;
  34. var PREF;
  35.  
  36. var kSOUNDContractID;
  37. var kSOUNDIID;
  38. var SOUND;
  39.  
  40. var kWINDOWContractID;
  41. var kWINDOWIID;
  42. var WINDOWSVC;
  43.  
  44. var kDSContractID;
  45. var kDSIID;
  46. var DS;
  47.  
  48. var kIOContractID;
  49. var kIOIID;
  50. var IOSVC;
  51.  
  52. var kMICSUMContractID;
  53. var kMICSUMIID;
  54. var MICSUMSVC;
  55.  
  56. var gBmProperties;
  57. var gBkmkTxnSvc;
  58.  
  59. var faves_coop;
  60.  
  61. var MAX_DUMP_DEPTH = 10;
  62.  
  63. function debug(aString)
  64. {
  65.   dump(aString + "\n");
  66. }
  67.  
  68. function dumpObj(obj)
  69. {
  70.   dump("Object Dump:\n");
  71.   dump (_dumpObj(obj) + "\n");
  72. }
  73.  
  74. function _dumpObj(obj, name, indent, depth)
  75. {
  76.   if (depth > MAX_DUMP_DEPTH) {
  77.     return indent + name + ": <Maximum Depth Reached>\n";
  78.   }
  79.  
  80.   if (typeof obj == "object") {
  81.     var child = null;
  82.     var output = indent + name + "\n";
  83.     indent += "\t";
  84.     for (var item in obj) {
  85.       try {
  86.         child = obj[item];
  87.       } catch (e) {
  88.         child = "<Unable to Evaluate>";
  89.       }
  90.       if (typeof child == "object") {
  91.         output += dumpObj(child, item, indent, depth + 1);
  92.       } else {
  93.         output += indent + item + ": " + child + "\n";
  94.       }
  95.     }
  96.     return output;
  97.   } else {
  98.     return obj;
  99.   }
  100. }
  101.  
  102.  
  103. function normalizeQuery(input)
  104. {
  105.   var output;
  106.   var in_quotes = false;
  107.  
  108.   // strip leading spaces
  109.   while (input.length && input[0]==" ") {
  110.     // chop off the first character
  111.     input = input.substr(1);
  112.   }
  113.  
  114.   // Convert to lowercase for the wildcard search
  115.   input = input.toLowerCase();
  116.  
  117.   // add leading plus
  118.   output = "+";
  119.   while (input.length) {
  120.     if (input[0] == "\"") {
  121.       if (in_quotes) {
  122.         in_quotes = false;
  123.       } else {
  124.         in_quotes = true;
  125.         // FIXME: remove spaces from the start of quoted strings
  126.       }
  127.     }
  128.  
  129.     // escape special chars
  130.     if ("&|!(){}[]^~*?:\\".indexOf(input[0]) >= 0) {
  131.       output = output + "\\";
  132.     }
  133.  
  134.     output = output + input[0];
  135.  
  136.     if (!in_quotes && input[0] == " " && input.length > 1) {
  137.         // put a plus before every word
  138.         output = output + "+";
  139.     }
  140.  
  141.     input = input.substr(1);
  142.   }
  143.  
  144.   // remove trailing spaces
  145.   var removed_spaces = false;
  146.   while (output.length > 0 && output[output.length - 1] == " ") {
  147.     output = output.substr(0, output.length - 1);
  148.     removed_spaces = true;
  149.   }
  150.  
  151.   // if we're in a quoted string we should close that
  152.   if (in_quotes) {
  153.     output = output + "\"";
  154.   }
  155.  
  156.   // if theres an incomplete word
  157.   if ((!removed_spaces) && (output[output.length - 1] != "\"")) {
  158.     // search for partial matches
  159.     output = output + "*";
  160.   }
  161.  
  162.   return output;
  163. }
  164.  
  165.  
  166. // should be moved in a separate file
  167. function initServices()
  168. {
  169.   gNC_NS     = "http://home.netscape.com/NC-rdf#";
  170.   gFL_NS     = "http://flock.com/rdf#";
  171.   gWEB_NS    = "http://home.netscape.com/WEB-rdf#";
  172.   gRDF_NS    = "http://www.w3.org/1999/02/22-rdf-syntax-ns#";
  173.   gXUL_NS    = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
  174.   gNC_NS_CMD = gNC_NS + "command?cmd=";
  175.  
  176.   kRDFContractID   = "@mozilla.org/rdf/rdf-service;1";
  177.   kRDFSVCIID       = Components.interfaces.nsIRDFService;
  178.   kRDFRSCIID       = Components.interfaces.nsIRDFResource;
  179.   kRDFLITIID       = Components.interfaces.nsIRDFLiteral;
  180.   RDF              = Components.classes[kRDFContractID].getService(kRDFSVCIID);
  181.  
  182.   kRDFCContractID  = "@mozilla.org/rdf/container;1";
  183.   kRDFCIID         = Components.interfaces.nsIRDFContainer;
  184.   RDFC             = Components.classes[kRDFCContractID].createInstance(kRDFCIID);
  185.  
  186.   kRDFCUContractID = "@mozilla.org/rdf/container-utils;1";
  187.   kRDFCUIID        = Components.interfaces.nsIRDFContainerUtils;
  188.   RDFCU            = Components.classes[kRDFCUContractID].getService(kRDFCUIID);
  189.  
  190.   kPREFContractID  = "@mozilla.org/preferences-service;1";
  191.   kPREFIID         = Components.interfaces.nsIPrefService;
  192.   PREF             = Components.classes[kPREFContractID].getService(kPREFIID)
  193.                                .getBranch(null);
  194.  
  195.   kSOUNDContractID = "@mozilla.org/sound;1";
  196.   kSOUNDIID        = Components.interfaces.nsISound;
  197.   SOUND            = Components.classes[kSOUNDContractID].createInstance(kSOUNDIID);
  198.  
  199.   kWINDOWContractID = "@mozilla.org/appshell/window-mediator;1";
  200.   kWINDOWIID        = Components.interfaces.nsIWindowMediator;
  201.   WINDOWSVC         = Components.classes[kWINDOWContractID].getService(kWINDOWIID);
  202.  
  203.   kDSContractID     = "@mozilla.org/widget/dragservice;1";
  204.   kDSIID            = Components.interfaces.nsIDragService;
  205.   DS                = Components.classes[kDSContractID].getService(kDSIID);
  206.  
  207.   kIOContractID     = "@mozilla.org/network/io-service;1";
  208.   kIOIID            = Components.interfaces.nsIIOService;
  209.   IOSVC             = Components.classes[kIOContractID].getService(kIOIID);
  210.   
  211.   kMICSUMContractID = "@mozilla.org/microsummary/service;1";
  212.   kMICSUMIID        = Components.interfaces.nsIMicrosummaryService;
  213.   // MICSUMSVC         = Components.classes[kMICSUMContractID].getService(kMICSUMIID);
  214.   
  215.   gBmProperties     = [RDF.GetResource(gNC_NS+"Name"),
  216.                        RDF.GetResource(gNC_NS+"URL"),
  217.                        RDF.GetResource(gNC_NS+"ShortcutURL"),
  218.                        RDF.GetResource(gNC_NS+"Description"),
  219.                        RDF.GetResource(gNC_NS+"WebPanel"),
  220.                        RDF.GetResource(gNC_NS+"FeedURL"),
  221.                        RDF.GetResource(gNC_NS+"MicsumGenURI"),
  222.                        RDF.GetResource(gNC_NS+"MicsumExpiration"),
  223.                        RDF.GetResource(gNC_NS+"GeneratedTitle"),
  224.                        RDF.GetResource(gNC_NS+"BookmarkAddDate"),
  225.                        RDF.GetResource(gWEB_NS+"LastModifiedDate"),
  226.                        RDF.GetResource(gWEB_NS+"LastVisitDate"),
  227.                        RDF.GetResource(gWEB_NS+"LastCharset"),
  228.                        RDF.GetResource(gFL_NS+"flockType"),
  229.                        RDF.GetResource(gFL_NS+"isTransient"),
  230.                        RDF.GetResource(gFL_NS+"isIndexable"),
  231.                        RDF.GetResource(gFL_NS+"unseenItems"),
  232.                        RDF.GetResource(gFL_NS+"count"),
  233.                        RDF.GetResource(gFL_NS+"maxItems"),
  234.                        RDF.GetResource(gFL_NS+"capItems"),
  235.                        RDF.GetResource(gFL_NS+"hasUnseenItems"),
  236.                        RDF.GetResource(gFL_NS+"isPollable"),
  237.                        RDF.GetResource(gFL_NS+"refreshing"),
  238.                        RDF.GetResource(gFL_NS+"shared"),
  239.                        RDF.GetResource(gFL_NS+"favicon"),
  240.                        RDF.GetResource(gFL_NS+"tags"),
  241.                        RDF.GetResource(gFL_NS+"lastItemDate"),
  242.                        RDF.GetResource(gFL_NS+"lastRefresh"),
  243.                        RDF.GetResource(gFL_NS+"lastQuery"),
  244.                        RDF.GetResource(gFL_NS+"refreshInterval"),
  245.                        RDF.GetResource(gFL_NS+"datevalue"),
  246.                        RDF.GetResource(gFL_NS+"CoopType"),
  247.                        RDF.GetResource(gRDF_NS+"type") ];
  248.   gBkmkTxnSvc = Components.classes["@mozilla.org/bookmarks/transactionmanager;1"]
  249.                           .getService(Components.interfaces.nsIBookmarkTransactionManager);
  250. }
  251.  
  252. function initBMService()
  253. {
  254.   kBMSVCIID = Components.interfaces.nsIBookmarksService;
  255.   kFFSVCIID = Components.interfaces.flockIFavoritesService;
  256.  
  257.   BMDS  = RDF.GetDataSource("rdf:flock-favorites");
  258.   faves_coop = Components.classes["@flock.com/singleton;1"]
  259.                          .getService(Components.interfaces.flockISingleton)
  260.                          .getSingleton("chrome://browser/content/flock/common/load-faves-coop.js")
  261.                          .wrappedJSObject;
  262.  
  263.   BMSVC = BMDS.QueryInterface(kBMSVCIID);
  264.   FFSVC = BMDS.QueryInterface(kFFSVCIID);
  265. }
  266.  
  267. /**
  268.  * XXX - 24 Jul 04
  269.  * If you add a command that needs to run from the main browser window,
  270.  * it needs to be added to browser/base/content/browser-sets.inc as well!
  271.  *
  272.  * XXX - 04/16/01
  273.  *  ACK! massive command name collision problems are causing big issues
  274.  *  in getting this stuff to work in the Navigator window. For sanity's 
  275.  *  sake, we need to rename all the commands to be of the form cmd_bm_*
  276.  *  otherwise there'll continue to be problems. For now, we're just 
  277.  *  renaming those that affect the personal toolbar (edit operations,
  278.  *  which were clashing with the textfield controller)
  279.  *
  280.  * There are also several places that need to be updated if you need
  281.  * to change a command name. 
  282.  *   1) the controller...
  283.  *      - in bookmarksTree.xml if the command is tree-specifc
  284.  *      - in bookmarksMenu.js if the command is DOM-specific
  285.  *      - in bookmarks.js otherwise
  286.  *   2) the command nodes in the overlay or xul file
  287.  *   3) the command human-readable name key in bookmarks.properties
  288.  *   4) the function 'getCommands' in bookmarks.js
  289.  */
  290.  
  291. var BookmarksCommand = {
  292.  
  293.   /////////////////////////////////////////////////////////////////////////////
  294.   // This method constructs a menuitem for a context menu for the given command.
  295.   // This is implemented by the client so that it can intercept menuitem naming
  296.   // as appropriate.
  297.   createMenuItem: function (aDisplayName, aAccessKey, aCommandName, aSelection)
  298.   {
  299.     var xulElement = document.createElementNS(gXUL_NS, "menuitem");
  300.     xulElement.setAttribute("cmd", aCommandName);
  301.     var cmd = "cmd_" + aCommandName.substring(gNC_NS_CMD.length);
  302.     xulElement.setAttribute("command", cmd);
  303.     xulElement.setAttribute("label", aDisplayName);
  304.     xulElement.setAttribute("accesskey", aAccessKey);
  305.     return xulElement;
  306.   },
  307.  
  308.   /////////////////////////////////////////////////////////////////////////////
  309.   // Fill a context menu popup with menuitems that are appropriate for the current
  310.   // selection.
  311.   createContextMenu: function (aEvent, aSelection, aDS)
  312.   {
  313.     if (aSelection == undefined) {
  314.       aEvent.preventDefault();
  315.       return;
  316.     }
  317.  
  318.     var popup = aEvent.target;
  319.     // clear out the old context menu contents (if any)
  320.     while (popup.hasChildNodes()) 
  321.       popup.removeChild(popup.firstChild);
  322.         
  323.     var commonCommands = [];
  324.     for (var i = 0; i < aSelection.length; ++i) {
  325.       var commands = this.getCommands(aSelection.item[i], aSelection.parent[i], aDS);
  326.       if (!commands) {
  327.         aEvent.preventDefault();
  328.         return;
  329.       }
  330.       commands = this.flattenEnumerator(commands);
  331.       if (!commonCommands.length) commonCommands = commands;
  332.       commonCommands = this.findCommonNodes(commands, commonCommands);
  333.     }
  334.  
  335.     if (!commonCommands.length) {
  336.       aEvent.preventDefault();
  337.       return;
  338.     }
  339.     
  340.     // Now that we should have generated a list of commands that is valid
  341.     // for the entire selection, build a context menu.
  342.     for (i = 0; i < commonCommands.length; ++i) {
  343.       var currCommand = commonCommands[i].QueryInterface(kRDFRSCIID).Value;
  344.       var element = null;
  345.       if (currCommand != gNC_NS_CMD + "bm_separator") {
  346.         var commandName = this.getCommandName(currCommand);
  347.         var accessKey = this.getAccessKey(currCommand);
  348.         element = this.createMenuItem(commandName, accessKey, currCommand, aSelection);
  349.       }
  350.       else if (i != 0 && i < commonCommands.length-1) {
  351.         // Never append a separator as the first or last element in a context
  352.         // menu.
  353.         element = document.createElementNS(gXUL_NS, "menuseparator");
  354.       }
  355.       if (element) 
  356.         popup.appendChild(element);
  357.     }
  358.  
  359.     if (popup.firstChild.getAttribute("command") == "cmd_bm_open")
  360.       popup.firstChild.setAttribute("default", "true");
  361.   },
  362.  
  363.   
  364.   /////////////////////////////////////////////////////////////////////////////
  365.   // Given two unique arrays, return an array that contains only the elements
  366.   // common to both. 
  367.   findCommonNodes: function (aNewArray, aOldArray)
  368.   {
  369.     var common = [];
  370.     for (var i = 0; i < aNewArray.length; ++i) {
  371.       for (var j = 0; j < aOldArray.length; ++j) {
  372.         if (common.length > 0 && common[common.length-1] == aNewArray[i])
  373.           continue;
  374.         if (aNewArray[i] == aOldArray[j])
  375.           common.push(aNewArray[i]);
  376.       }
  377.     }
  378.     return common;
  379.   },
  380.  
  381.   flattenEnumerator: function (aEnumerator)
  382.   {
  383.     if ("_index" in aEnumerator)
  384.       return aEnumerator._inner;
  385.     
  386.     var temp = [];
  387.     while (aEnumerator.hasMoreElements()) 
  388.       temp.push(aEnumerator.getNext());
  389.     return temp;
  390.   },
  391.   
  392.   /////////////////////////////////////////////////////////////////////////////
  393.   // For a given URI (a unique identifier of a resource in the graph) return 
  394.   // an enumeration of applicable commands for that URI. 
  395.   getCommands: function (aNodeID, aParent, aDS)
  396.   {
  397.     var type = BookmarksUtils.resolveType(aNodeID, aDS);
  398.     if (!type)
  399.       return null;
  400.  
  401.     var ptype = null;
  402.     aParent =  (aParent != null) ? aParent : BMSVC.getParent(aNodeID);
  403.     if (aParent) {
  404.       ptype = BookmarksUtils.resolveType(aParent, aDS);
  405.       if (ptype == "Livemark") {
  406.         type = "LivemarkBookmark";
  407.       }
  408.     }
  409.  
  410.     var coopObj = faves_coop.get_from_resource(aNodeID);
  411.  
  412.     var commands = [];
  413.     // menu order:
  414.     // 
  415.     // bm_open, bm_openfolder
  416.     // bm_openinnewwindow
  417.     // bm_openinnewtab
  418.     // ---------------------
  419.     // bm_newfolder
  420.     // ---------------------
  421.     // cut
  422.     // copy
  423.     // paste
  424.     // ---------------------
  425.     // delete
  426.     // ---------------------
  427.     // bm_refreshlivemark
  428.     // bm_refreshmicrosummary
  429.     // bm_sortbyname
  430.     // ---------------------
  431.     // bm_properties
  432.     switch (type) {
  433.     case "BookmarkSeparator":
  434.       commands = ["bm_newbookmark", "bm_newfolder", "bm_newseparator", "bm_separator",
  435.                   "cut", "copy", "paste", "bm_separator",
  436.                   "delete", "bm_separator",
  437.                   "bm_separator",
  438.                   "bm_properties"];
  439.       break;
  440.     case "Bookmark":
  441.       commands = ["bm_open", "bm_openinnewwindow", "bm_openinnewtab", "bm_separator",
  442.                   "bm_newbookmark", "bm_newfolder", "bm_newseparator", "bm_separator",
  443.                   "cut", "copy", "paste", "bm_separator",
  444.                   "delete", "bm_separator",
  445.                   "bm_properties"];
  446.       // If this bookmark has a microsummary, add a command for refreshing it
  447.       // right before the "sort by name" (bm_sortbyname) command.
  448.       // ERWAN: Deactivate microsummaries for now
  449.       // if (MICSUMSVC.hasMicrosummary(aNodeID))
  450.       //  commands.splice(14, 0, "bm_refreshmicrosummary");
  451.         
  452.       break;
  453.     case "Folder":
  454.     case "PersonalToolbarFolder":
  455.       commands = ["bm_openfolder", "bm_separator", "bm_newbookmark", 
  456.                   "bm_newfolder", "bm_newseparator", "bm_separator",
  457.                   "cut", "copy", "paste", "bm_separator",
  458.                   "delete",
  459.                   "bm_properties"];
  460.       break;
  461.     case "IEFavoriteFolder":
  462.       commands = ["bm_separator", "delete"];
  463.       break;
  464.     case "IEFavorite":
  465.       commands = ["bm_open", "bm_openinnewwindow", "bm_openinnewtab", "bm_separator",
  466.                   "copy"];
  467.       break;
  468.     case "FileSystemObject":
  469.       commands = ["bm_open", "bm_openinnewwindow", "bm_openinnewtab", "bm_separator",
  470.                   "copy"];
  471.       break;
  472.     case "Livemark":
  473.       commands = ["bm_openfolder", "bm_separator",
  474.                   "cut", "copy", "bm_separator",
  475.                   "delete", "bm_separator",
  476.                   "bm_refreshlivemark", 
  477.                   "bm_properties"];
  478.       break;
  479.     case "LivemarkBookmark":
  480.       commands = ["bm_open", "bm_openinnewwindow", "bm_openinnewtab", "bm_separator",
  481.                   "copy"];
  482.       break;
  483.     case "ImmutableBookmark":
  484.       commands = ["bm_open", "bm_openinnewwindow", "bm_openinnewtab"];
  485.       break;
  486.     default: 
  487.       commands = [];
  488.       dump("No commands for selection of type " + type + "\n");
  489.     }
  490.  
  491.     return new CommandArrayEnumerator(commands);
  492.   },
  493.   
  494.   /////////////////////////////////////////////////////////////////////////////
  495.   // Retrieve the human-readable name for a particular command. Used when 
  496.   // manufacturing a UI to invoke commands.
  497.   getCommandName: function (aCommand) 
  498.   {
  499.     var cmdName = aCommand.substring(gNC_NS_CMD.length);
  500.     
  501.     return BookmarksUtils.getLocaleString ("cmd_" + cmdName) ? BookmarksUtils.getLocaleString ("cmd_" + cmdName)  : BookmarksUtils.getPeopleLocaleString(cmdName);
  502.   },
  503.  
  504.   /////////////////////////////////////////////////////////////////////////////
  505.   // Retrieve the access key for a particular command. Used when 
  506.   // manufacturing a UI to invoke commands.
  507.   getAccessKey: function (aCommand) 
  508.   {
  509.     var cmdName = aCommand.substring(gNC_NS_CMD.length);
  510.     return BookmarksUtils.getLocaleString ("cmd_" + cmdName + "_accesskey");
  511.   },
  512.   
  513.   ///////////////////////////////////////////////////////////////////////////
  514.   // Execute a command with the given source and arguments
  515.   doBookmarksCommand: function (aSource, aCommand, aArgumentsArray)
  516.   {
  517.     var rCommand = RDF.GetResource(aCommand);
  518.   
  519.     var kSuppArrayContractID = "@mozilla.org/supports-array;1";
  520.     var kSuppArrayIID = Components.interfaces.nsISupportsArray;
  521.     var sourcesArray = Components.classes[kSuppArrayContractID].createInstance(kSuppArrayIID);
  522.     if (aSource) {
  523.       sourcesArray.AppendElement(aSource);
  524.     }
  525.   
  526.     var argsArray = Components.classes[kSuppArrayContractID].createInstance(kSuppArrayIID);
  527.     var length = aArgumentsArray?aArgumentsArray.length:0;
  528.     for (var i = 0; i < length; ++i) {
  529.       var rArc = RDF.GetResource(aArgumentsArray[i].property);
  530.       argsArray.AppendElement(rArc);
  531.       var rValue = null;
  532.       if ("resource" in aArgumentsArray[i]) { 
  533.         rValue = RDF.GetResource(aArgumentsArray[i].resource);
  534.       }
  535.       else
  536.         rValue = RDF.GetLiteral(aArgumentsArray[i].literal);
  537.       argsArray.AppendElement(rValue);
  538.     }
  539.  
  540.     // Exec the command in the Bookmarks datasource. 
  541.     BMDS.DoCommand(sourcesArray, rCommand, argsArray);
  542.   },
  543.  
  544.   undoBookmarkTransaction: function ()
  545.   {
  546.     gBkmkTxnSvc.undo();
  547.     BookmarksUtils.refreshSearch();
  548.     BookmarksUtils.flushDataSource();
  549.   },
  550.  
  551.   redoBookmarkTransaction: function ()
  552.   {
  553.     gBkmkTxnSvc.redo();
  554.     BookmarksUtils.refreshSearch();
  555.     BookmarksUtils.flushDataSource();
  556.   },
  557.  
  558.   manageFolder: function (aSelection)
  559.   {
  560.     openDialog("chrome://browser/content/bookmarks/bookmarksManager.xul", 
  561.                "", "chrome,all,dialog=no", aSelection.item[0].Value);
  562.   },
  563.   
  564.   cutBookmark: function (aSelection)
  565.   {
  566.     this.copyBookmark(aSelection);
  567.     if(aSelection.item.length >0)
  568.     {
  569.       var obj = faves_coop.get(aSelection.item[0].Value); 
  570.       var parents = obj.getParents();
  571.       // topsites will also be a parent of this bookmark, hence remove from all
  572.       // of the parents
  573.       for (var idx in parents) {
  574.         var parent = parents[idx];
  575.         if (parent && parent.children) {
  576.           parent.children.remove(obj);
  577.         }
  578.       }
  579.     }
  580.     if (document.getElementById("bookmarks-view")) {
  581.       document.getElementById("bookmarks-view").refreshTree();
  582.     }
  583.   },
  584.   
  585.   copyBookmark: function (aSelection)
  586.   {
  587.     const kSuppArrayContractID = "@mozilla.org/supports-array;1";
  588.     const kSuppArrayIID = Components.interfaces.nsISupportsArray;
  589.     var itemArray = Components.classes[kSuppArrayContractID].createInstance(kSuppArrayIID);
  590.  
  591.     const kSuppWStringContractID = "@mozilla.org/supports-string;1";
  592.     const kSuppWStringIID = Components.interfaces.nsISupportsString;
  593.     var bmstring = Components.classes[kSuppWStringContractID].createInstance(kSuppWStringIID);
  594.     var unicodestring = Components.classes[kSuppWStringContractID].createInstance(kSuppWStringIID);
  595.     var htmlstring = Components.classes[kSuppWStringContractID].createInstance(kSuppWStringIID);
  596.   
  597.     var sBookmarkItem = ""; var sTextUnicode = ""; var sTextHTML = ""; var tmpBmItem = [];
  598.     for (var i = 0; i < aSelection.length; ++i) {
  599.       sBookmarkItem += aSelection.item[i].Value + "\n";
  600.  
  601.       // save the selection property into text string that we will use later in paste function
  602.       // and in INSERT tranasactions
  603.       // (if the selection is folder or livemark save all childs property)
  604.       var aType = BookmarksUtils.resolveType(aSelection.item[i]);
  605.       if (aType == "Livemark") {
  606.          //sBookmarkItem += "\n\n\n\n\n\n\n\n\n"; // don't change livemark properties
  607.          for (var j = 0; j < gBmProperties.length; j++) {
  608.             sBookmarkItem += "\n";
  609.          }
  610.       } else {
  611.          for (var j = 0; j < gBmProperties.length; ++j) {
  612.             var itemValue = BMDS.GetTarget(aSelection.item[i], gBmProperties[j], true);
  613.             if (itemValue) {
  614.                 if(aType == "BookmarkSeparator")
  615.                 {
  616.                   sBookmarkItem += itemValue.QueryInterface(kRDFLITIID).Value + "\n";
  617.                   break;
  618.                 }
  619.                 sBookmarkItem += BookmarksUtils.getNodeInterface(itemValue).Value + "\n";
  620.               
  621.             } else {
  622. //dump("CDC:  no target value for "+gBmProperties[j].Value+"\n");
  623.                 sBookmarkItem += "\n";
  624.             }
  625.          }
  626.       }
  627.       var childCount = 1;
  628.       if (aType == "Folder" || aType == "Livemark") {
  629.          var propArray = [];
  630.          BookmarksUtils.getAllChildren(aSelection.item[i], propArray);
  631.          for (var k = 0; k < propArray.length; ++k) {
  632.             for (var j = 0; j < gBmProperties.length + 1; ++j) {
  633.                if (propArray[k][j])
  634.                    sBookmarkItem += propArray[k][j].Value + "\n";
  635.                else
  636.                    sBookmarkItem += "\n";
  637.             }
  638.          }
  639.          childCount += propArray.length;
  640.       }
  641.       tmpBmItem.push(childCount +  "\n" + sBookmarkItem);
  642.       sBookmarkItem = "";
  643.  
  644.       var url;
  645.       if (aType == "Livemark")
  646.         url = BookmarksUtils.getProperty(aSelection.item[i], gNC_NS+"FeedURL");
  647.       else
  648.         url = BookmarksUtils.getProperty(aSelection.item[i], gNC_NS+"URL");
  649.  
  650.       var name = BookmarksUtils.getProperty(aSelection.item[i], gNC_NS+"Name");
  651.  
  652.       sTextUnicode += url + "\n";
  653.       sTextHTML += "<A HREF=\"" + url + "\">" + name + "</A>";
  654.     }
  655.     sTextUnicode = sTextUnicode.replace(/\n$/,"");
  656.  
  657.     // generate unique separator and combine the array to one string 
  658.     var bmSeparator = "]-[", extrarSeparator = "@";
  659.     for (var i = 0; i < tmpBmItem.length; ++i) {
  660.         while (tmpBmItem[i].indexOf(bmSeparator)>-1)
  661.            bmSeparator += extrarSeparator;
  662.     }
  663.     for (var i = 0; i < tmpBmItem.length; ++i) {
  664.       sBookmarkItem += tmpBmItem[i] + bmSeparator;
  665.     }
  666.     // insert the separator to sBookmarkItem so we can extract it in pasteBookmark
  667.     sBookmarkItem = bmSeparator + "\n" + sBookmarkItem;
  668.     
  669.     const kXferableContractID = "@mozilla.org/widget/transferable;1";
  670.     const kXferableIID = Components.interfaces.nsITransferable;
  671.     var xferable = Components.classes[kXferableContractID].createInstance(kXferableIID);
  672.  
  673.     xferable.addDataFlavor("moz/bookmarkclipboarditem");
  674.     bmstring.data = sBookmarkItem;
  675.     xferable.setTransferData("moz/bookmarkclipboarditem", bmstring, sBookmarkItem.length*2);
  676.     
  677.     xferable.addDataFlavor("text/html");
  678.     htmlstring.data = sTextHTML;
  679.     xferable.setTransferData("text/html", htmlstring, sTextHTML.length*2);
  680.     
  681.     xferable.addDataFlavor("text/unicode");
  682.     unicodestring.data = sTextUnicode;
  683.     xferable.setTransferData("text/unicode", unicodestring, sTextUnicode.length*2);
  684.     
  685.     const kClipboardContractID = "@mozilla.org/widget/clipboard;1";
  686.     const kClipboardIID = Components.interfaces.nsIClipboard;
  687.     var clipboard = Components.classes[kClipboardContractID].getService(kClipboardIID);
  688.     clipboard.setData(xferable, null, kClipboardIID.kGlobalClipboard);
  689.   },
  690.  
  691.   getTargetURNString: function()
  692.   {
  693.      dump('getTargetURNString ' +'\n');
  694.     const kXferableContractID = "@mozilla.org/widget/transferable;1";
  695.     const kXferableIID = Components.interfaces.nsITransferable;
  696.     var xferable = Components.classes[kXferableContractID].createInstance(kXferableIID);
  697.     xferable.addDataFlavor("moz/bookmarkclipboarditem");
  698.     xferable.addDataFlavor("text/x-moz-url");
  699.     xferable.addDataFlavor("text/unicode");
  700.  
  701.     const kClipboardContractID = "@mozilla.org/widget/clipboard;1";
  702.     const kClipboardIID = Components.interfaces.nsIClipboard;
  703.     var clipboard = Components.classes[kClipboardContractID].getService(kClipboardIID);
  704.     clipboard.getData(xferable, kClipboardIID.kGlobalClipboard);
  705.     
  706.     var flavour = { };
  707.     var data    = { };
  708.     var length  = { };
  709.     xferable.getAnyTransferData(flavour, data, length);
  710.     var items, name, url, childs, removedProps = [];
  711.     data = data.value.QueryInterface(Components.interfaces.nsISupportsString).data;
  712.     dump('getTargetURNString '+ data +'\n');
  713.     return data;
  714.   },
  715.   
  716.   pasteBookmark: function (aTarget)
  717.   {
  718.     const kXferableContractID = "@mozilla.org/widget/transferable;1";
  719.     const kXferableIID = Components.interfaces.nsITransferable;
  720.     var xferable = Components.classes[kXferableContractID].createInstance(kXferableIID);
  721.     xferable.addDataFlavor("moz/bookmarkclipboarditem");
  722.     xferable.addDataFlavor("text/x-moz-url");
  723.     xferable.addDataFlavor("text/unicode");
  724.  
  725.     const kClipboardContractID = "@mozilla.org/widget/clipboard;1";
  726.     const kClipboardIID = Components.interfaces.nsIClipboard;
  727.     var clipboard = Components.classes[kClipboardContractID].getService(kClipboardIID);
  728.     clipboard.getData(xferable, kClipboardIID.kGlobalClipboard);
  729.     
  730.     var flavour = { };
  731.     var data    = { };
  732.     var length  = { };
  733.     xferable.getAnyTransferData(flavour, data, length);
  734.     var items, name, url, childs, removedProps = [];
  735.     data = data.value.QueryInterface(Components.interfaces.nsISupportsString).data;
  736.     switch (flavour.value) {
  737.     case "moz/bookmarkclipboarditem":
  738.       var tmpItem = data.split("\n");
  739.       var sep = tmpItem.shift();
  740.       data = tmpItem.join("\n");
  741.       items = data.split(sep);
  742.       // since data are ended by separator, remove the last empty node
  743.       items.pop(); 
  744.       // convert propery from text string to array
  745.       var p = gBmProperties.length+1;
  746.       // Find the index of the 'rdf:type' property
  747.       var typeIdx;
  748.       for (typeIdx = 0; typeIdx < gBmProperties.length; typeIdx++) {
  749.         if (gBmProperties[typeIdx].Value == "http://flock.com/rdf#flockType") {
  750.           break;
  751.         }
  752.       }
  753.       for (var i = 0; i < items.length; ++i) {
  754.         childs = items[i].split("\n");
  755.         childs.pop();
  756.         var childCount = childs.shift();
  757.         // Is this child a Folder?
  758.         if (childs[typeIdx] && childs[typeIdx].toLowerCase() == "folder") {
  759.           // When pasting a folder, we want to ensure that it has a *different*
  760.           // RDF id from the original folder, so we create a new folder and
  761.           // remove the default parentage, since it will be recreated as a
  762.           // child of the folder being pasted
  763.           var newFldrRes = BMSVC.createFolder("TempName");
  764.           var c_fldr = BookmarksUtils.getflockUtilsObject().BookmarksShareUtils
  765.                                      .getCoopObject(BMDS, newFldrRes);
  766.           var parent = c_fldr.getParent();
  767.           parent.children.remove(c_fldr);
  768.           items[i] = newFldrRes;
  769.         } else {
  770.           items[i] = RDF.GetResource(childs[0]);
  771.         }
  772.         var propArray = [];
  773.         for (var k = 0; k < childCount; ++k) {
  774.           for (var j = 1; j < p; ++j) {
  775.              var prop = childs[p*k+j];
  776.              if (prop) {
  777.                 if(prop instanceof Components.interfaces.nsIRDFLiteral) 
  778.                    propArray.push(RDF.GetLiteral(prop));
  779.                 else if(prop instanceof Components.interfaces.nsIRDFDate)
  780.                    propArray.push(RDF.GetDateLiteral(prop));
  781.                 else if(prop instanceof Components.interfaces.nsIRDFInt)
  782.                    propArray.push(RDF.GetIntLiteral(prop));
  783.                 else
  784.                    propArray.push(null);
  785.              } else {
  786.                 propArray.push(null);
  787.              }
  788.           }
  789.         }
  790.         removedProps.push(propArray);
  791.       }
  792.       break;
  793.     case "text/x-moz-url":
  794.       // there should be only one item in this case
  795.       var ix = data.indexOf("\n");
  796.       items = data.substring(0, ix != -1 ? ix : data.length);
  797.       name  = data.substring(ix);
  798.       // XXX: we should infer the best charset
  799.       var createdBookmarkResource = BookmarksUtils.createBookmark(null, items, null, name, null);
  800.       items = [createdBookmarkResource];
  801.       break;
  802.     default: 
  803.       return;
  804.     }
  805.     var parent = Array(items.length);
  806.     parent[0] = aTarget.parent;
  807.     var selection = {item: items, parent: parent, length: items.length, prop: removedProps};
  808.     BookmarksUtils.checkSelection(selection);
  809.     BookmarksUtils.insertAndCheckSelection("paste", selection, aTarget, -1);
  810.   },
  811.   
  812.   deleteBookmark: function (aSelection)
  813.   {
  814.     //dump("CDC: deleteBookmark()\n");
  815.     // call checkSelection here to update the immutable and other
  816.     // flags on the selection; when new resources get created,
  817.     // they're temporarily not valid because they're not in a
  818.     // bookmark container.  So, they can't be removed until that's
  819.     // fixed.
  820.     BookmarksUtils.checkSelection(aSelection);
  821.     BookmarksUtils.removeAndCheckSelection("delete", aSelection);
  822.     if (document.getElementById('bookmarks-view'))
  823.       document.getElementById('bookmarks-view').refreshTree();
  824.   },
  825.  
  826.   moveBookmark: function (aSelection)
  827.   {
  828.     var rv = { selectedFolder: null };      
  829.     openDialog("chrome://browser/content/bookmarks/addBookmark.xul", "", 
  830.                "centerscreen,chrome,modal=yes,dialog=yes,resizable=yes", null, 
  831.                null, null, null, "selectFolder", rv);
  832.     if (!rv.target)
  833.       return;
  834.     BookmarksUtils.moveAndCheckSelection("move", aSelection, rv.target);
  835.     if (document.getElementById('bookmarks-view'))
  836.       document.getElementById('bookmarks-view').refreshTree();
  837.   },
  838.  
  839.   openBookmark: function (aSelection, aTargetBrowser, aDS) 
  840.   {
  841.     if (!aTargetBrowser)
  842.       return;
  843.  
  844.     // in this case, we can just use |aSelection.length| as "Open in Tabs"
  845.     // is only available when you are only selecting multiple bookmarks
  846.     // if you selected a folder of bookmarks, we check the number of tabs in
  847.     // openGroupBookmark()
  848.     if (aTargetBrowser == "tab" && !this._confirmOpenTabs(aSelection.length))
  849.       return;
  850.  
  851.     for (var i=0; i<aSelection.length; ++i) {
  852.       var type = aSelection.type[i];
  853.       dump ("openBookmark of type " + type + "\n");
  854.       if (aTargetBrowser == "save") {
  855.         this.saveBookmark(aSelection.item[i].Value, aDS);
  856.       }
  857.       else if (type == "Bookmark" || type == "ImmutableBookmark") {
  858.         var webPanel = BMDS.GetTarget(aSelection.item[i],
  859.                                       RDF.GetResource(gNC_NS + "WebPanel"),
  860.                                       true);
  861.         if (webPanel && aTargetBrowser == "current")
  862.           this.openWebPanel(aSelection.item[i].Value, aDS);
  863.         else
  864.           this.openOneBookmark(aSelection.item[i].Value, aTargetBrowser, aDS);
  865.       }
  866.       else if (type == "Folder" || type == "PersonalToolbarFolder" || type == "Livemark")
  867.         this.openGroupBookmark(aSelection.item[i].Value, aTargetBrowser);
  868.     }
  869.   },
  870.   
  871.   openBookmarkProperties: function (aSelection) 
  872.   {
  873.     // Bookmark Properties dialog is only ever opened with one selection 
  874.     // (command is disabled otherwise)
  875.     var bookmark = aSelection.item[0].Value;
  876.     //dump("CDC: openBookmarkProperties('"+bookmark+"')\n");
  877.     var value = {};
  878.     openDialog("chrome://browser/content/bookmarks/bookmarksProperties.xul", "", "centerscreen,chrome,modal,resizable=no", aSelection, value);
  879.     if (value.gResource) {
  880.       gResource = value.gResource;
  881.       //gResource.QueryInterface(Components.interfaces.nsIRDFResource);
  882.       //dump("CDC:  gResource = "+gResource.Value+"\n");
  883.       var bookmarksView = document.getElementById("bookmarks-view");
  884.       if (bookmarksView) {
  885.         bookmarksView.treeBoxObject.view.selection.selectEventsSuppressed = true;
  886.         bookmarksView.treeBoxObject.view.selection.clearSelection();
  887.         bookmarksView.selectResource(gResource);
  888.       }
  889.     }
  890.     var bmFoldersTree = document.getElementById("bookmark-folders-view");
  891.     if (bmFoldersTree) bmFoldersTree.refreshTree();
  892.     var bmFullTree = document.getElementById("bookmarks-view");
  893.     if (bmFullTree) bmFullTree.refreshTree();
  894.     return value.ok;
  895.   },
  896.  
  897.   // requires utilityOverlay.js if opening in new window for getTopWin()
  898.   openWebPanel: function(aResource, aDS)
  899.   {
  900.     var url = BookmarksUtils.getProperty(aResource, gNC_NS+"URL", aDS);
  901.     // Ignore "NC:" and empty urls.
  902.     if (url == "")
  903.       return;
  904.     var w = getTopWin();
  905.     if (!w) {
  906.       openDialog(getBrowserURL(), "_blank", "chrome,all,dialog=no", url);
  907.       return;
  908.     }
  909.     w.openWebPanel(BookmarksUtils.getProperty(aResource,  gNC_NS+"Name"), url);
  910.   },
  911.  
  912.   // requires contentAreaUtils.js because it calls saveURL
  913.   saveBookmark: function(aResource, aDS)
  914.   {
  915.     var url = BookmarksUtils.getProperty(aResource, gNC_NS+"URL", aDS);
  916.     // Ignore "NC:" and empty urls.
  917.     if (url == "")
  918.       return;
  919.     var fileName = BookmarksUtils.getProperty(aResource, gNC_NS+"Name", aDS);
  920.  
  921.     saveURL(url, fileName, null, true); 
  922.   },
  923.  
  924.   // requires utilityOverlay.js because it calls openUILinkIn
  925.   openOneBookmark: function (aURI, aTargetBrowser, aDS)
  926.   {
  927.     var url = BookmarksUtils.getProperty(aURI, gNC_NS+"URL", aDS);
  928.     // Ignore "NC:" and empty urls.
  929.     if (url == "")
  930.       return;
  931.  
  932.     var metrics = Components.classes['@flock.com/metrics-service;1']
  933.       .getService(Components.interfaces.flockIMetricsService);
  934.     metrics.reportCount('favorite visit');
  935.  
  936.     var w = getTopWin();
  937.     if (w) {
  938.       var browser  = w.document.getElementById("content");
  939.       if( browser.currentURI.spec == "about:myworld") {
  940.         openUILinkIn(url, "tab");
  941.         return;
  942.       }
  943.     } 
  944.       
  945.     openUILinkIn(url, aTargetBrowser);
  946.   },
  947.  
  948.   _confirmOpenTabs: function(numTabsToOpen) 
  949.   {
  950.     var reallyOpen = true;
  951.  
  952.     const kWarnOnOpenPref = "browser.tabs.warnOnOpen";
  953.     if (PREF.getBoolPref(kWarnOnOpenPref))
  954.     {
  955.       if (numTabsToOpen >= PREF.getIntPref("browser.tabs.maxOpenBeforeWarn"))
  956.       {
  957.         var promptService = 
  958.             Components.classes["@mozilla.org/embedcomp/prompt-service;1"].
  959.             getService(Components.interfaces.nsIPromptService);
  960.  
  961.         // default to true: if it were false, we wouldn't get this far
  962.         var warnOnOpen = { value: true };
  963.  
  964.         var messageKey = "tabs.openWarningMultipleBranded";
  965.         var openKey = "tabs.openButtonMultiple";
  966.  
  967.         var buttonPressed = promptService.confirmEx(window,
  968.             BookmarksUtils.getLocaleString("tabs.openWarningTitle"),
  969.             BookmarksUtils.getLocaleString(messageKey, 
  970.               [numTabsToOpen, BookmarksUtils._brandShortName]),
  971.             (promptService.BUTTON_TITLE_IS_STRING * promptService.BUTTON_POS_0)
  972.             + (promptService.BUTTON_TITLE_CANCEL * promptService.BUTTON_POS_1),
  973.             BookmarksUtils.getLocaleString(openKey),
  974.             null, null,
  975.             BookmarksUtils.getLocaleString("tabs.openWarningPromptMeBranded",
  976.                [BookmarksUtils._brandShortName]),
  977.             warnOnOpen);
  978.  
  979.          reallyOpen = (buttonPressed == 0);
  980.          // don't set the pref unless they press OK and it's false
  981.          if (reallyOpen && !warnOnOpen.value)
  982.            PREF.setBoolPref(kWarnOnOpenPref, false);
  983.        }
  984.     }
  985.     return reallyOpen;
  986.   },
  987.  
  988.   openGroupBookmark: function (aURI, aTargetBrowser)
  989.   {
  990.     var w = getTopWin();
  991.     if (!w)
  992.       // no browser window is open, we have to open the group into a new window
  993.       aTargetBrowser = "window";
  994.  
  995.     var resource = RDF.GetResource(aURI);
  996.     var urlArc   = RDF.GetResource(gNC_NS+"URL");
  997.     RDFC.Init(BMDS, resource);
  998.     var containerChildren = RDFC.GetElements();
  999.     var numTabsToOpen = 0;
  1000.  
  1001.     // we can't just use |RDFC.GetCount()| as that might include
  1002.     // folders, separators, deleted bookmarks, etc.
  1003.     while (containerChildren.hasMoreElements()) {
  1004.       var res = containerChildren.getNext().QueryInterface(kRDFRSCIID);
  1005.       var type = BookmarksUtils.resolveType(res);
  1006.       // these are the types in getCommands() that support the 
  1007.       // "bm_openinnewwindow" and "bm_openinnewtab" commands
  1008.       if (type == "Bookmark" || type == "LivemarkBookmark" || 
  1009.           type == "ImmutableBookmark" || type == "IEFavorite" ||
  1010.           type == "FileSystemObject")
  1011.         numTabsToOpen++;
  1012.     }
  1013.  
  1014.     if (!this._confirmOpenTabs(numTabsToOpen))
  1015.       return;
  1016.  
  1017.     var metrics = Components.classes['@flock.com/metrics-service;1']
  1018.       .getService(Components.interfaces.flockIMetricsService);
  1019.     metrics.reportCount('favoriteGroup visit');
  1020.  
  1021.     // counting the number of tabs to open modified the 
  1022.     // containerChildren enumerator, so we need to reset it.
  1023.     containerChildren = RDFC.GetElements();
  1024.     if (aTargetBrowser == "current" || aTargetBrowser == "tab") {
  1025.       var browser  = w.document.getElementById("content");
  1026.       var tabPanels = browser.browsers;
  1027.       var tabCount  = tabPanels.length;
  1028.       var doReplace = PREF.getBoolPref("browser.tabs.loadFolderAndReplace");
  1029.       var loadInBackground = PREF.getBoolPref("browser.tabs.loadBookmarksInBackground");
  1030.       var index0;
  1031.       if (doReplace)
  1032.         index0 = 0;
  1033.       else {
  1034.         for (index0=tabCount-1; index0>=0; --index0)
  1035.         {
  1036.           var tab = tabPanels[index0];
  1037.           if (tab.webNavigation.currentURI.spec != "about:blank" ||
  1038.               tab.webProgress.isLoadingDocument)
  1039.             break;
  1040.         }
  1041.         ++index0;
  1042.       }
  1043.  
  1044.       var index = index0;
  1045.       while (containerChildren.hasMoreElements()) {
  1046.         var res = containerChildren.getNext().QueryInterface(kRDFRSCIID);
  1047.         var target = BMDS.GetTarget(res, urlArc, true);
  1048.         if (target) {
  1049.           var uri = target.QueryInterface(kRDFLITIID).Value;
  1050.           if (index < tabCount)
  1051.             tabPanels[index].loadURI(uri);
  1052.           else {
  1053.             // This is not a modal sub-action of a given tab/document within a window
  1054.             // since opening a bookmarks group replaces all existing tabs in the window,
  1055.             // closing extras. If this ever changes to be augmentative, this code will
  1056.             // have to change to probably just use <tabbrowser>.loadTabs() which figures
  1057.             // out whether or not owner should be set. 
  1058.             browser.addTab(uri);
  1059.           }
  1060.           ++index;
  1061.         }
  1062.       }
  1063.  
  1064.       // If the bookmark group was completely invalid, just bail.
  1065.       if (index == index0)
  1066.         return;
  1067.  
  1068.       // focus the first tab if prefs say to
  1069.       if (!loadInBackground || doReplace) {
  1070.         // Select the first tab in the group.
  1071.         // Set newly selected tab after quick timeout, otherwise hideous focus problems
  1072.         // can occur because new presshell is not ready to handle events
  1073.         function selectNewForegroundTab(browser, tab) {
  1074.           browser.selectedTab = tab;
  1075.         }
  1076.         var tabs = browser.mTabContainer.childNodes;
  1077.         setTimeout(selectNewForegroundTab, 0, browser, tabs[index0]);
  1078.       }
  1079.  
  1080.       // Close any remaining open tabs that are left over.
  1081.       // (Always skipped when we append tabs)
  1082.       for (var i = tabCount-1; i >= index; --i)
  1083.         browser.removeTab(tabs[i]);
  1084.  
  1085.       // and focus the content
  1086.       w.content.focus();
  1087.  
  1088.     } else if (aTargetBrowser == "window") {
  1089.       var URIs = [];
  1090.  
  1091.       while (containerChildren.hasMoreElements()) {
  1092.         var res = containerChildren.getNext().QueryInterface(kRDFRSCIID);
  1093.         var target = BMDS.GetTarget(res, urlArc, true);
  1094.         if (target)
  1095.           URIs.push(target.QueryInterface(kRDFLITIID).Value);
  1096.       }
  1097.  
  1098.       openDialog(getBrowserURL(), "_blank", "chrome,all,dialog=no", URIs.join("|"));
  1099.     }
  1100.   },
  1101.  
  1102.   createNewBookmark: function (aTarget, aSelection)
  1103.   {
  1104.     var name     = BookmarksUtils.getLocaleString("ile_newbookmark");
  1105.     var type = BookmarksUtils.resolveType(aSelection.item[0]);
  1106.     if(type == 'Folder' || type== "PersonalToolbarFolder")
  1107.     {
  1108.       var resource = BMDS.addBookmarkToFolder(aSelection.item[0].Value,name, "", "", "", "", null,"");
  1109.       aTarget.parent = aSelection.item[0];
  1110.     }else
  1111.     {
  1112.       var resource = BMDS.createBookmarkWithTags(name, "", "", "", "", null,"");
  1113.     }
  1114.     this.createNewResource(resource, aTarget, "newbookmark");
  1115.   },
  1116.  
  1117.   createNewLivemark: function (aTarget)
  1118.   {
  1119.     var name     = BookmarksUtils.getLocaleString("ile_newlivemark");
  1120.     var dArgs = {
  1121.       name: name
  1122.     };
  1123.     
  1124.     openDialog("chrome://browser/content/bookmarks/addLivemark.xul", "", "centerscreen,chrome,dialog,resizable,modal", dArgs);
  1125.     // var resource = BMSVC.createLivemark(name, "", "about:blank", null);
  1126.     // this.createNewResource(resource, aTarget, "newlivemark");
  1127.   },
  1128.  
  1129.   createNewFolder: function (aTarget)
  1130.   {
  1131.     var name     = BookmarksUtils.getLocaleString("ile_newfolder");
  1132.     var resource = BMSVC.createFolder(name);
  1133.     this.createNewResource(resource, aTarget, "newfolder");
  1134.     // temporary hack...
  1135.     return resource;
  1136.   },
  1137.  
  1138.   createNewSeparator: function (aTarget)
  1139.   {
  1140.     var resource = BMSVC.createSeparator();
  1141.     this.createNewResource(resource, aTarget, "newseparator");
  1142.   },
  1143.  
  1144.   createNewResource: function(aResource, aTarget, aTxnType)
  1145.   {
  1146.     var selection = BookmarksUtils.getSelectionFromResource(aResource, aTarget.parent);
  1147.     var ok        = BookmarksUtils.insertAndCheckSelection(aTxnType, selection, aTarget, -1);
  1148.  
  1149.     // This bookmark resource was just added.  If it has FoldersRoot as a
  1150.     // parent, then that error must be corrected.
  1151.     var c_fldr = BookmarksUtils.getflockUtilsObject().BookmarksShareUtils
  1152.                                .getCoopObject(BMDS, aResource);
  1153.     var parents = c_fldr.getParents();
  1154.     var parentLength = 1;
  1155.      // We will have 2 default parents for Flock bookmark favorites:  http://flock.com/rdf#BookmarksRoot && favorite:topsites
  1156.     if(aTxnType =='newbookmark')
  1157.     {
  1158.       parentLength = 2;
  1159.     }
  1160.     if (parents.length > parentLength) {
  1161.       for (var i = 0; i < parents.length; i++) {
  1162.         if (parents[i].id() == "http://flock.com/rdf#FoldersRoot") {
  1163.           parents[i].children.remove(c_fldr);
  1164.           break;
  1165.         }
  1166.       }
  1167.     }
  1168.  
  1169.     // When this resource was initially created, it was given BookmarksRoot as
  1170.     // a parent.  Then in insertAndCheckSelection it was attached to its real
  1171.     // parent.  So now, remove the BookmarksRoot connection unless it is the
  1172.     // only parent.
  1173.     parents = c_fldr.getParents();
  1174.     if (parents.length > parentLength) {
  1175.       for (var i = 0; i < parents.length; i++) {
  1176.         if (parents[i].id() == "http://flock.com/rdf#BookmarksRoot") {
  1177.           parents[i].children.remove(c_fldr);
  1178.           break;
  1179.         }
  1180.       }
  1181.     }
  1182.     if (aTxnType != "newseparator") {
  1183.       ok = this.openBookmarkProperties(selection);
  1184.       if (!ok)
  1185.         BookmarksCommand.deleteBookmark(selection);
  1186.     }
  1187.   },
  1188.  
  1189.   importBookmarks: function ()
  1190.   {
  1191.       // XXX: ifdef it to be non-modal (non-"sheet") on mac (see bug 259039)
  1192.       var features = "modal,centerscreen,chrome,resizable=no";
  1193.       window.fromFile = false;
  1194.       window.openDialog("chrome://browser/content/migration/migration.xul", "migration", features, "bookmarks");
  1195.       if(window.fromFile)
  1196.       {
  1197.         this.importBookmarksFromFile();
  1198.       }
  1199.   },
  1200.  
  1201.   importBookmarksFromFile: function ()
  1202.   {
  1203.     ///transaction...
  1204.     try {
  1205.       const kFilePickerContractID = "@mozilla.org/filepicker;1";
  1206.       const kFilePickerIID = Components.interfaces.nsIFilePicker;
  1207.       const kFilePicker = Components.classes[kFilePickerContractID].createInstance(kFilePickerIID);
  1208.     
  1209.       const kTitle = BookmarksUtils.getLocaleString("SelectImport");
  1210.       kFilePicker.init(window, kTitle, kFilePickerIID["modeOpen"]);
  1211.       kFilePicker.appendFilters(kFilePickerIID.filterHTML | kFilePickerIID.filterAll);
  1212.       var fileName;
  1213.       if (kFilePicker.show() != kFilePickerIID.returnCancel) {
  1214.         fileName = kFilePicker.file.path;
  1215.         if (!fileName) return;
  1216.       }
  1217.       else return;
  1218.     }
  1219.     catch (e) {
  1220.       return;
  1221.     }
  1222.     rTarget = RDF.GetResource(gFL_NS+"FoldersRoot");
  1223.     RDFC.Init(BMDS, rTarget);
  1224.     var countBefore = parseInt(BookmarksUtils.getProperty(rTarget, gRDF_NS+"nextVal"));
  1225.     var args = [{ property: gNC_NS+"URL", literal: fileName}];
  1226.     this.doBookmarksCommand(rTarget, gNC_NS_CMD+"import", args);
  1227.     var countAfter = parseInt(BookmarksUtils.getProperty(rTarget, gRDF_NS+"nextVal"));
  1228.  
  1229.     if (countAfter - countBefore > 1)
  1230.       gBkmkTxnSvc.startBatch();
  1231.     for (var index = countBefore; index < countAfter; index++) {
  1232.       var nChildArc = RDFCU.IndexToOrdinalResource(index);
  1233.       var rChild    = BMDS.GetTarget(rTarget, nChildArc, true);
  1234.       gBkmkTxnSvc.createAndCommitTxn(gBkmkTxnSvc.IMPORT, "IMPORT", rChild, index,
  1235.                                     rTarget, 0, null);
  1236.     }
  1237.     if (countAfter - countBefore > 1)
  1238.       gBkmkTxnSvc.endBatch();
  1239.  
  1240.     BookmarksUtils.flushDataSource();
  1241.   },
  1242.  
  1243.   exportBookmarks: function ()
  1244.   {
  1245.     try {
  1246.       const kFilePickerContractID = "@mozilla.org/filepicker;1";
  1247.       const kFilePickerIID = Components.interfaces.nsIFilePicker;
  1248.       const kFilePicker = Components.classes[kFilePickerContractID].createInstance(kFilePickerIID);
  1249.       
  1250.       const kTitle = BookmarksUtils.getLocaleString("EnterExport");
  1251.       kFilePicker.init(window, kTitle, kFilePickerIID["modeSave"]);
  1252.       kFilePicker.appendFilters(kFilePickerIID.filterHTML | kFilePickerIID.filterAll);
  1253.       kFilePicker.defaultString = "bookmarks.html";
  1254.       var fileName;
  1255.       if (kFilePicker.show() != kFilePickerIID.returnCancel) {
  1256.         fileName = kFilePicker.file.path;
  1257.         if (!fileName) return;
  1258.       }
  1259.       else return;
  1260.  
  1261.       var file = Components.classes["@mozilla.org/file/local;1"]
  1262.                            .createInstance(Components.interfaces.nsILocalFile);
  1263.       if (!file)
  1264.         return;
  1265.       file.initWithPath(fileName);
  1266.       if (!file.exists()) {
  1267.         file.create(Components.interfaces.nsIFile.NORMAL_FILE_TYPE, 0644);
  1268.       }
  1269.       BMDS.writeBookmarks(file);
  1270.     }
  1271.     catch (e) {
  1272.       return;
  1273.     }
  1274.     var selection = RDF.GetResource(gFL_NS+"FoldersRoot");
  1275.     var args = [{ property: gNC_NS+"URL", literal: fileName}];
  1276.    //this.doBookmarksCommand(selection, gNC_NS_CMD+"export", args);
  1277.     
  1278.   },
  1279.  
  1280.   refreshLivemark: function (aSelection)
  1281.   {
  1282.     var exp = RDF.GetResource(gNC_NS+"LivemarkExpiration");
  1283.     for (var i = 0; i < aSelection.length; i++) {
  1284.       rsrc = RDF.GetResource(aSelection.item[i].Value);
  1285.       oldtgt = BMDS.GetTarget(rsrc, exp, true);
  1286.       if (oldtgt) {
  1287.         BMDS.Unassert(rsrc, exp, oldtgt);
  1288.       }
  1289.     }
  1290.   },
  1291.  
  1292.   refreshMicrosummary: function (aSelection)
  1293.   {
  1294.     // ERWAN: Deactivate microsummaries for now
  1295.     //for (var i = 0; i < aSelection.length; i++) {
  1296.     //  rsrc = RDF.GetResource(aSelection.item[i].Value);
  1297.     //  MICSUMSVC.refreshMicrosummary(rsrc);
  1298.     //}
  1299.   },
  1300.  
  1301.   sortByName: function (aSelection)
  1302.   {
  1303.     // do the real sorting in a timeout, to make sure that
  1304.     // if we sort from a menu that the menu gets torn down
  1305.     // before we sort.  the template builder really doesn't
  1306.     // like it if we move things around; the menu code also
  1307.     // doesn't like it if we move the menuparent while a
  1308.     // popup is open.
  1309.     setTimeout(function () { BookmarksCommand.realSortByName(aSelection); }, 0);
  1310.   },
  1311.  
  1312.   realSortByName: function (aSelection)
  1313.   {
  1314.     var theFolder;
  1315.  
  1316.     if (aSelection.length != 1)
  1317.       return;
  1318.  
  1319.     var selType = BookmarksUtils.resolveType(aSelection.item[0]);
  1320.     if (selType == "Folder" || selType == "Bookmark" ||
  1321.         selType == "PersonalToolbarFolder" || selType == "Livemark")
  1322.     {
  1323.       theFolder = aSelection.parent[0];
  1324.     } else {
  1325.       // we're not going to try to sort ImmutableBookmark siblings or
  1326.       // any other such thing, since it'll probably just get us into
  1327.       // trouble
  1328.       return;
  1329.     }
  1330.  
  1331.     var toSort = [];
  1332.     RDFC.Init(BMDS, theFolder);
  1333.     var folderContents = RDFC.GetElements();
  1334.     while (folderContents.hasMoreElements()) {
  1335.         var rsrc = folderContents.getNext().QueryInterface(kRDFRSCIID);
  1336.         var rtype = BookmarksUtils.resolveType(rsrc);
  1337.         if (rtype == "BookmarkSeparator")
  1338.           continue;
  1339.         toSort.push(rsrc);
  1340.     }
  1341.  
  1342.     const kName = RDF.GetResource(gNC_NS+"Name");
  1343.  
  1344.     var localeService = Components.classes["@mozilla.org/intl/nslocaleservice;1"]
  1345.                                   .getService(Components.interfaces.nsILocaleService);
  1346.     var collationFactory = Components.classes["@mozilla.org/intl/collation-factory;1"]
  1347.                                      .getService(Components.interfaces.nsICollationFactory);
  1348.     var collation = collationFactory.CreateCollation(localeService.getApplicationLocale());
  1349.  
  1350.     toSort.sort (function (a, b) {
  1351.                    var atype = BookmarksUtils.resolveType(a);
  1352.                    var btype = BookmarksUtils.resolveType(b);
  1353.  
  1354.                    var aisfolder = (atype == "Folder") || (atype == "PersonalToolbarFolder");
  1355.                    var bisfolder = (btype == "Folder") || (btype == "PersonalToolbarFolder");
  1356.  
  1357.                    // folders above bookmarks
  1358.                    if (aisfolder && !bisfolder)
  1359.                      return -1;
  1360.                    if (bisfolder && !aisfolder)
  1361.                      return 1;
  1362.  
  1363.                    // then sort by name
  1364.                    var aname = BMDS.GetTarget(a, kName, true).QueryInterface(kRDFLITIID).Value;
  1365.                    var bname = BMDS.GetTarget(b, kName, true).QueryInterface(kRDFLITIID).Value;
  1366.  
  1367.                    return collation.compareString(0, aname, bname);
  1368.                  });
  1369.  
  1370.     // we now have the resources here sorted by name
  1371.     BMDS.beginUpdateBatch();
  1372.  
  1373.     RDFC.Init(BMDS, theFolder);
  1374.  
  1375.     // remove existing elements
  1376.     var folderContents = RDFC.GetElements();
  1377.     while (folderContents.hasMoreElements()) {
  1378.       RDFC.RemoveElement (folderContents.getNext(), false);
  1379.     }
  1380.  
  1381.     // and add our elements back
  1382.     for (var i = 0; i < toSort.length; i++) {
  1383.       RDFC.InsertElementAt (toSort[i], i+1, true);
  1384.     }
  1385.  
  1386.     BMDS.endUpdateBatch();
  1387.   }
  1388.  
  1389. }
  1390.  
  1391.   /////////////////////////////////////////////////////////////////////////////
  1392.   // Command handling & Updating.
  1393. var BookmarksController = {
  1394.  
  1395.   supportsCommand: function (aCommand)
  1396.   {
  1397.     var isCommandSupported;
  1398.     switch(aCommand) {
  1399.     case "cmd_undo":
  1400.     case "cmd_redo":
  1401.     case "cmd_bm_undo":
  1402.     case "cmd_bm_redo":
  1403.     case "cmd_cut":
  1404.     case "cmd_copy":
  1405.     case "cmd_paste":
  1406.     case "cmd_delete":
  1407.     case "cmd_selectAll":
  1408.     case "cmd_bm_open":
  1409.     case "cmd_bm_openinnewwindow":
  1410.     case "cmd_bm_openinnewtab":
  1411.     case "cmd_bm_openfolder":
  1412.     case "cmd_bm_managefolder":
  1413.     case "cmd_bm_newbookmark":
  1414.     case "cmd_bm_newlivemark":
  1415.     case "cmd_bm_newfolder":
  1416.     case "cmd_bm_newseparator":
  1417.     case "cmd_bm_properties":
  1418.     case "cmd_bm_rename":
  1419.     case "cmd_bm_setnewbookmarkfolder":
  1420.     case "cmd_bm_setpersonaltoolbarfolder":
  1421.     case "cmd_bm_setnewsearchfolder":
  1422.     case "cmd_bm_import":
  1423.     case "cmd_bm_export":
  1424.     case "cmd_bm_movebookmark":
  1425.     case "cmd_bm_refreshlivemark":
  1426.     case "cmd_bm_refreshmicrosummary":
  1427.     case "cmd_bm_sortbyname":
  1428.       isCommandSupported = true;
  1429.       break;
  1430.     default:
  1431.       // JMC - If there's an arc in services, add a command?
  1432.       // No - each service has it's own commandController
  1433.       isCommandSupported = false;
  1434.     }
  1435.     //if (!isCommandSupported)
  1436.     //  dump("Bookmark command '"+aCommand+"' is not supported!\n");
  1437.     return isCommandSupported;
  1438.   },
  1439.  
  1440.   isCommandEnabled: function (aCommand, aSelection, aTarget)
  1441.   {
  1442.     var item0, type0, junk, parent0, ptype0, isOnline;
  1443.     var length = 0;
  1444.     if (aSelection && aSelection.length != 0) {
  1445.       length = aSelection.length;
  1446.       item0 = aSelection.item[0].Value;
  1447.       type0 = aSelection.type[0];
  1448.       parent0 =  (aSelection.parent[0] != null) ? aSelection.parent[0] : BMSVC.getParent(aSelection.item[0]);
  1449.       ptype0 = BookmarksUtils.resolveType(parent0);
  1450.       coopitem = faves_coop.get(item0);
  1451.       var coopparent = coopitem;
  1452.       while (coopparent && (coopparent.id() != "http://flock.com/rdf#OnlineBookmarksRoot"))
  1453.         coopparent = coopparent.getParent();
  1454.       isOnline = !!coopparent;
  1455.     }
  1456.     var i;
  1457.  
  1458.     switch(aCommand) {
  1459.     case "cmd_undo":
  1460.     case "cmd_bm_undo":
  1461.       return gBkmkTxnSvc.canUndo();
  1462.     case "cmd_redo":
  1463.     case "cmd_bm_redo":
  1464.       return gBkmkTxnSvc.canRedo();
  1465.     case "cmd_paste":
  1466.       if (ptype0 == "Livemark" || (aTarget && !BookmarksUtils.isValidTargetContainer(aTarget.parent)))
  1467.         return false;
  1468.       const kClipboardContractID = "@mozilla.org/widget/clipboard;1";
  1469.       const kClipboardIID = Components.interfaces.nsIClipboard;
  1470.       var clipboard = Components.classes[kClipboardContractID].getService(kClipboardIID);
  1471.       const kSuppArrayContractID = "@mozilla.org/supports-array;1";
  1472.       const kSuppArrayIID = Components.interfaces.nsISupportsArray;
  1473.       var flavourArray = Components.classes[kSuppArrayContractID].createInstance(kSuppArrayIID);
  1474.       const kSuppStringContractID = "@mozilla.org/supports-cstring;1";
  1475.       const kSuppStringIID = Components.interfaces.nsISupportsCString;
  1476.     
  1477.       var flavours = ["moz/bookmarkclipboarditem", "text/x-moz-url"];
  1478.       for (i = 0; i < flavours.length; ++i) {
  1479.         const kSuppString = Components.classes[kSuppStringContractID].createInstance(kSuppStringIID);
  1480.         kSuppString.data = flavours[i];
  1481.         flavourArray.AppendElement(kSuppString);
  1482.       }
  1483.       // dump ("JMC>> Gonna return hasMAtchingFlavours...\n");
  1484.       var hasFlavours = clipboard.hasDataMatchingFlavors(flavourArray, kClipboardIID.kGlobalClipboard);
  1485.       return hasFlavours;
  1486.     case "cmd_copy":
  1487.       return length > 0;
  1488.     case "cmd_cut":
  1489.     case "cmd_delete":
  1490.       return length > 0 && !aSelection.containsImmutable && ptype0 != "Livemark" && !aSelection.containsPTF && !isOnline;
  1491.     case "cmd_selectAll":
  1492.       return true;
  1493.     case "cmd_bm_open":
  1494.     case "cmd_bm_managefolder":
  1495.       return length == 1;
  1496.     case "cmd_bm_openinnewwindow":
  1497.     case "cmd_bm_openinnewtab":
  1498.       return true;
  1499.     case "cmd_bm_openfolder":
  1500.      
  1501.       for (i=0; i<length; ++i) {
  1502.         if (aSelection.type[i] == "ImmutableBookmark" ||
  1503.             aSelection.type[i] == "ImmutableFolder" ||
  1504.             aSelection.type[i] == "Bookmark" ||
  1505.             aSelection.type[i] == "BookmarkSeparator")
  1506.           return false;
  1507.         RDFC.Init(BMDS, aSelection.item[i]);
  1508.         var children = RDFC.GetElements();
  1509.         while (children.hasMoreElements()) {
  1510.           var childType = BookmarksUtils.resolveType(children.getNext());
  1511.           if (childType == "Bookmark" || childType == "LivemarkBookmark")
  1512.             return true;
  1513.         }
  1514.       }
  1515.       return false;
  1516.     case "cmd_bm_import":
  1517.     case "cmd_bm_export":
  1518.       return true;
  1519.     case "cmd_bm_newbookmark":
  1520.     case "cmd_bm_newlivemark":
  1521.     case "cmd_bm_newfolder":
  1522.     case "cmd_bm_newseparator":
  1523.        return  (ptype0 != "Livemark" && ((type0 == "PersonalToolbarFolder") ||
  1524.                 (aTarget && BookmarksUtils.isValidTargetContainer(aTarget.parent))) && !isOnline);
  1525.     case "cmd_bm_properties":
  1526.       return aSelection.item.length > 0 &&  (!(aSelection.item[0]  && 
  1527.            aSelection.item[0].Value == "http://flock.com/rdf#BookmarksRoot") || 
  1528.           (ptype0 == "Livemark") );
  1529.     case "cmd_bm_rename":
  1530.        if(!BookmarksUtils.isValidTargetContainer(aTarget.parent) || isOnline)
  1531.         return false;
  1532.       if (aSelection.item.length < 1  || (aSelection.item[0]  && 
  1533.            aSelection.item[0].Value == "http://flock.com/rdf#BookmarksRoot") || 
  1534.           (ptype0 == "Livemark") ) {
  1535.             return false;
  1536.       }else
  1537.             return true;
  1538.     case "cmd_bm_setpersonaltoolbarfolder":
  1539.       if (length != 1 || type0 == "Livemark" || isOnline)
  1540.         return false;
  1541.       return item0 != BMSVC.getBookmarksToolbarFolder().Value && 
  1542.              item0 != gFL_NS+"FoldersRoot" && type0 == "Folder";
  1543.     case "cmd_bm_movebookmark":
  1544.       if(aSelection == null || aSelection.item.length < 1)
  1545.       {
  1546.         return false
  1547.       }
  1548.       if (aSelection.containsImmutable  == null) {
  1549.         aSelection.containsImmutable = false;
  1550.         length = 1;
  1551.         aSelection.item[0].Value = "";
  1552.       }
  1553.       return length > 0 && 
  1554.              !aSelection.containsImmutable &&
  1555.              ptype0 != "Livemark" &&
  1556.              aSelection.item[0] &&
  1557.              aSelection.item[0].Value != "http://flock.com/rdf#BookmarksRoot" &&
  1558.               BookmarksUtils.isValidTargetContainer(aTarget.parent); 
  1559.     case "cmd_bm_refreshlivemark":
  1560.       for (i=0; i<length; ++i) {
  1561.         if (aSelection.type[i] != "Livemark")
  1562.           return false;
  1563.       }
  1564.       return length > 0;
  1565.     case "cmd_bm_refreshmicrosummary":
  1566.       return false;
  1567.       // ERWAN: Deactivate microsummaries for now
  1568.       //for (i=0; i<length; ++i) {
  1569.       //  if (!MICSUMSVC.hasMicrosummary(aSelection.item[i]))
  1570.       //    return false;
  1571.       //}
  1572.       return length > 0;
  1573.     case "cmd_bm_sortbyname":
  1574.       if (length == 1 && (aSelection.type[0] == "Folder" ||
  1575.                           aSelection.type[0] == "Bookmark" ||
  1576.                           aSelection.type[0] == "PersonalToolbarFolder" ||
  1577.                           aSelection.type[0] == "Livemark"))
  1578.         return true;
  1579.       return false;
  1580.     default:
  1581.       return false;
  1582.     }
  1583.   },
  1584.  
  1585.   doCommand: function (aCommand, aSelection, aTarget, aDS)
  1586.   {
  1587.     //dump("CDC: bookmarks.js: doCommand('"+aCommand+"', aTarget= "+((aTarget) ? aTarget.Value : aTarget)+", aDS= "+aDS+")\n");
  1588.     
  1589.     var resource0, type0, realTarget;
  1590.     if (aSelection && aSelection.length == 1) {
  1591.       resource0 = aSelection.item[0];
  1592.       //dump("CDC: bookmarks.js:           aSelection.item[0].Value="+resource0.Value+"\n");
  1593.       type0 = aSelection.type[0];
  1594.     }
  1595.  
  1596.     if (type0 == "PersonalToolbarFolder" && aTarget == null)
  1597.       realTarget = { parent: resource0, index: -1 };
  1598.     else
  1599.       realTarget = aTarget;
  1600.  
  1601.     switch (aCommand) {
  1602.     case "cmd_undo":
  1603.     case "cmd_bm_undo":
  1604.       BookmarksCommand.undoBookmarkTransaction();
  1605.       break;
  1606.     case "cmd_redo":
  1607.     case "cmd_bm_redo":
  1608.       BookmarksCommand.redoBookmarkTransaction();
  1609.       break;
  1610.     case "cmd_bm_open":
  1611.       BookmarksCommand.openBookmark(aSelection, "current", aDS);
  1612.       break;
  1613.     case "cmd_bm_openinnewwindow":
  1614.       BookmarksCommand.openBookmark(aSelection, "window", aDS);
  1615.       break;
  1616.     case "cmd_bm_openinnewtab":
  1617.       BookmarksCommand.openBookmark(aSelection, "tab", aDS);
  1618.       break;
  1619.     case "cmd_bm_openfolder":
  1620.       BookmarksCommand.openBookmark(aSelection, "current", aDS);
  1621.       break;
  1622.     case "cmd_bm_managefolder":
  1623.       BookmarksCommand.manageFolder(aSelection);
  1624.       break;
  1625.     case "cmd_bm_setnewbookmarkfolder":
  1626.     case "cmd_bm_setpersonaltoolbarfolder":
  1627.     case "cmd_bm_setnewsearchfolder":
  1628.       BookmarksCommand.doBookmarksCommand(aSelection.item[0], gNC_NS_CMD+aCommand.substring("cmd_bm_".length), []);
  1629.       break;
  1630.     case "cmd_bm_rename":
  1631.     case "cmd_bm_properties":
  1632.       junk = BookmarksCommand.openBookmarkProperties(aSelection);
  1633.       break;
  1634.     case "cmd_cut":
  1635.       BookmarksCommand.cutBookmark(aSelection);
  1636.       break;
  1637.     case "cmd_copy":
  1638.       BookmarksCommand.copyBookmark(aSelection);
  1639.       break;
  1640.     case "cmd_paste":
  1641.       BookmarksCommand.pasteBookmark(realTarget);
  1642.       break;
  1643.     case "cmd_delete":
  1644.       BookmarksCommand.deleteBookmark(aSelection);
  1645.       break;
  1646.     case "cmd_bm_movebookmark":
  1647.       BookmarksCommand.moveBookmark(aSelection);
  1648.       break;
  1649.     case "cmd_bm_newbookmark":
  1650.       BookmarksCommand.createNewBookmark(realTarget, aSelection);
  1651.       break;
  1652.     case "cmd_bm_newlivemark":
  1653.       BookmarksCommand.createNewLivemark(realTarget);
  1654.       break;
  1655.     case "cmd_bm_newfolder":
  1656.       BookmarksCommand.createNewFolder(realTarget);
  1657.       break;
  1658.     case "cmd_bm_newseparator":
  1659.       BookmarksCommand.createNewSeparator(realTarget);
  1660.       break;
  1661.     case "cmd_bm_import":
  1662.       BookmarksCommand.importBookmarks();
  1663.       break;
  1664.     case "cmd_bm_export":
  1665.       BookmarksCommand.exportBookmarks();
  1666.       break;
  1667.     case "cmd_bm_refreshlivemark":
  1668.       BookmarksCommand.refreshLivemark(aSelection);
  1669.       break;
  1670.     case "cmd_bm_refreshmicrosummary":
  1671.       BookmarksCommand.refreshMicrosummary(aSelection);
  1672.       break;
  1673.     case "cmd_bm_sortbyname":
  1674.       BookmarksCommand.sortByName(aSelection);
  1675.       break;
  1676.     default: 
  1677.       dump("Bookmark command "+aCommand+" not handled!\n");
  1678.     }
  1679.  
  1680.   },
  1681.  
  1682.   onCommandUpdate: function (aSelection, aTarget)
  1683.   {
  1684.     var commands = ["cmd_bm_newbookmark", "cmd_bm_newlivemark", "cmd_bm_newfolder", "cmd_bm_newseparator",
  1685.                     "cmd_undo", "cmd_redo", "cmd_bm_properties", "cmd_bm_rename", 
  1686.                     "cmd_copy", "cmd_paste", "cmd_cut", "cmd_delete",
  1687.                     "cmd_bm_setpersonaltoolbarfolder", "cmd_bm_movebookmark",
  1688.                     "cmd_bm_openfolder", "cmd_bm_managefolder", "cmd_bm_refreshlivemark",
  1689.                     "cmd_bm_refreshmicrosummary", "cmd_bm_sortbyname"];
  1690.     for (var i = 0; i < commands.length; ++i) {
  1691.       var enabled = this.isCommandEnabled(commands[i], aSelection, aTarget);
  1692.       var commandNode = document.getElementById(commands[i]);
  1693.      if (commandNode) { 
  1694.         if (enabled) 
  1695.           commandNode.removeAttribute("disabled");
  1696.         else 
  1697.           commandNode.setAttribute("disabled", "true");
  1698.       }
  1699.     }
  1700.   }
  1701. }
  1702.  
  1703. function CommandArrayEnumerator (aCommandArray)
  1704. {
  1705.   this._inner = [];
  1706.   for (var i = 0; i < aCommandArray.length; ++i)
  1707.     this._inner.push(RDF.GetResource(gNC_NS_CMD + aCommandArray[i]));
  1708.     
  1709.   this._index = 0;
  1710. }
  1711.  
  1712. CommandArrayEnumerator.prototype = {
  1713.   getNext: function () 
  1714.   {
  1715.     return this._inner[this._index];
  1716.   },
  1717.   
  1718.   hasMoreElements: function ()
  1719.   {
  1720.     return this._index < this._inner.length;
  1721.   }
  1722. };
  1723.  
  1724. var BookmarksUtils = {
  1725.  
  1726.   DROP_BEFORE: Components.interfaces.nsITreeView.DROP_BEFORE,
  1727.   DROP_ON    : Components.interfaces.nsITreeView.DROP_ON,
  1728.   DROP_AFTER : Components.interfaces.nsITreeView.DROP_AFTER,
  1729.  
  1730.   _bundle        : null,
  1731.   _brandShortName: null,
  1732.   _observerService: null,
  1733.   /////////////////////////////////////////////////////////////////////////////////////
  1734.   // returns a property from chrome://browser/locale/bookmarks/bookmarks.properties
  1735.   getLocaleString: function (aStringKey, aReplaceString)
  1736.   {
  1737.     if (!this._bundle) {
  1738.       // for those who would xblify Bookmarks.js, there is a need to create string bundle 
  1739.       // manually instead of using <xul:stringbundle/> see bug 63370 for details
  1740.       var LOCALESVC = Components.classes["@mozilla.org/intl/nslocaleservice;1"]
  1741.                                 .getService(Components.interfaces.nsILocaleService);
  1742.       var BUNDLESVC = Components.classes["@mozilla.org/intl/stringbundle;1"]
  1743.                                 .getService(Components.interfaces.nsIStringBundleService);
  1744.       var bookmarksBundle  = "chrome://browser/locale/bookmarks/bookmarks.properties";
  1745.       this._bundle         = BUNDLESVC.createBundle(bookmarksBundle, LOCALESVC.getApplicationLocale());
  1746.       var brandBundle      = "chrome://branding/locale/brand.properties";
  1747.       this._brandShortName = BUNDLESVC.createBundle(brandBundle,     LOCALESVC.getApplicationLocale())
  1748.                                       .GetStringFromName("brandShortName");
  1749.       var peopleBundle = "chrome://browser/locale/flock/people/people.properties";
  1750.       this._peopleBundle = BUNDLESVC.createBundle(peopleBundle, LOCALESVC.getApplicationLocale());
  1751.     }
  1752.    
  1753.     var bundle;
  1754.     try {
  1755.       if (!aReplaceString)
  1756.         bundle = this._bundle.GetStringFromName(aStringKey);
  1757.       else if (typeof(aReplaceString) == "string")
  1758.         bundle = this._bundle.formatStringFromName(aStringKey, [aReplaceString], 1);
  1759.       else
  1760.         bundle = this._bundle.formatStringFromName(aStringKey, aReplaceString, aReplaceString.length);
  1761.     } catch (e) {
  1762.       dump("Bookmark bundle "+aStringKey+" not found!\n");
  1763.       bundle = "";
  1764.     }
  1765.  
  1766.     bundle = bundle.replace(/%brandShortName%/, this._brandShortName);
  1767.     return bundle;
  1768.   },
  1769.  
  1770.   getPeopleLocaleString: function (aStringKey, aReplaceString)
  1771.   {
  1772.     if (!this._peopleBundle) {
  1773.       // for those who would xblify Bookmarks.js, there is a need to create string bundle 
  1774.       // manually instead of using <xul:stringbundle/> see bug 63370 for details
  1775.       var LOCALESVC = Components.classes["@mozilla.org/intl/nslocaleservice;1"]
  1776.                                 .getService(Components.interfaces.nsILocaleService);
  1777.       var BUNDLESVC = Components.classes["@mozilla.org/intl/stringbundle;1"]
  1778.                                 .getService(Components.interfaces.nsIStringBundleService);
  1779.       var brandBundle      = "chrome://branding/locale/brand.properties";
  1780.       this._brandShortName = BUNDLESVC.createBundle(brandBundle,     LOCALESVC.getApplicationLocale())
  1781.                                       .GetStringFromName("brandShortName");
  1782.       var peopleBundle = "chrome://browser/locale/flock/people/people.properties";
  1783.       this._peopleBundle = BUNDLESVC.createBundle(peopleBundle, LOCALESVC.getApplicationLocale());
  1784.     }
  1785.    
  1786.    // JMC - Need to merge these in from the various services
  1787.    return aStringKey;
  1788.    
  1789.    var bundle;
  1790.    try {
  1791.      if (!aReplaceString)
  1792.        bundle = this._peopleBundle.GetStringFromName(aStringKey);
  1793.      else if (typeof(aReplaceString) == "string")
  1794.        bundle = this._peopleBundle.formatStringFromName(aStringKey, [aReplaceString], 1);
  1795.      else
  1796.        bundle = this._peopleBundle.formatStringFromName(aStringKey, aReplaceString, aReplaceString.length);
  1797.     } catch (e) {
  1798.       dump("People bundle "+aStringKey+" not found!\n");
  1799.       bundle = "";
  1800.     }
  1801.  
  1802.     bundle = bundle.replace(/%brandShortName%/, this._brandShortName);
  1803.     return bundle;
  1804.   },
  1805.   
  1806.   /////////////////////////////////////////////////////////////////////////////
  1807.   // returns the literal targeted by the URI aArcURI for a resource or uri
  1808.   getProperty: function (aInput, aArcURI, aDS)
  1809.   {
  1810.     var node;
  1811.     var arc  = RDF.GetResource(aArcURI);
  1812.     if (typeof(aInput) == "string") 
  1813.       aInput = RDF.GetResource(aInput);
  1814.     if (!aDS)
  1815.       node = BMDS.GetTarget(aInput, arc, true);
  1816.     else
  1817.       node = aDS .GetTarget(aInput, arc, true);
  1818.     try {
  1819.       return node.QueryInterface(kRDFRSCIID).Value;
  1820.     }
  1821.     catch (e) {
  1822.       return node? node.QueryInterface(kRDFLITIID).Value : "";
  1823.     }    
  1824.   },
  1825.  
  1826.   /////////////////////////////////////////////////////////////////////////////
  1827.   // queries the correct interface based on the node type
  1828.   getNodeInterface: function (aRDFNode)
  1829.   {
  1830.     if(aRDFNode instanceof Components.interfaces.nsIRDFLiteral) 
  1831.        return aRDFNode.QueryInterface(Components.interfaces.nsIRDFLiteral);
  1832.     if(aRDFNode instanceof Components.interfaces.nsIRDFDate) 
  1833.        return aRDFNode.QueryInterface(Components.interfaces.nsIRDFDate);
  1834.     if(aRDFNode instanceof Components.interfaces.nsIRDFResource) 
  1835.        return aRDFNode.QueryInterface(Components.interfaces.nsIRDFResource);
  1836.     return aRDFNode.QueryInterface(Components.interfaces.nsIRDFInt);
  1837.   },
  1838.   
  1839.   /////////////////////////////////////////////////////////////////////////////
  1840.   // Determine the rdf:type property for the given resource.
  1841.   resolveType: function (aResource, aDS)
  1842.   {
  1843.     // dump ("JMC>>: Resolve Type for " + aResource + " on DS + " + aDS + "\n");
  1844.     // JMC - Report favorites as bookmark type-nodes for actions, etc.
  1845.     var type = this.getProperty(aResource, gRDF_NS+"type", aDS);
  1846.     // dump ("JMC>>: " + type + "\n");
  1847.     
  1848.     if (type != "") {
  1849.       type = type.split("#")[1];
  1850.     }
  1851.     if (type == "Folder" || type == "Collection") {
  1852.       if (aResource == BMSVC.getBookmarksToolbarFolder())
  1853.         type = "PersonalToolbarFolder";
  1854.     }
  1855.     // Treat microsummary bookmarks like regular bookmarks, since they behave
  1856.     // like regular bookmarks in almost every regard.
  1857.     if (type == "MicsumBookmark" || type == "Favorite")
  1858.       type = "Bookmark";
  1859.  
  1860.     if (type == "") {
  1861.       // we're not sure what type it is.  figure out if it's a container.
  1862.       var child = this.getProperty(aResource, gNC_NS+"child", aDS);
  1863.       if (child || (RDF.GetResource(aResource)  && RDFCU.IsContainer(aDS?aDS:BMDS, RDF.GetResource(aResource))))
  1864.         return "ImmutableFolder";
  1865.  
  1866.       // not a container; make sure it has at least a URL
  1867.       if (this.getProperty(aResource, gNC_NS+"URL") != null)
  1868.         return "ImmutableBookmark";
  1869.     }
  1870.  
  1871.     return type;
  1872.   },
  1873.  
  1874.   
  1875.   /////////////////////////////////////////////////////////////////////////////
  1876.   // Caches frequently used informations about the selection
  1877.   checkSelection: function (aSelection)
  1878.   {
  1879.     // JMC - People are not containers. (But really, they are...)
  1880.     
  1881.     if (aSelection.length == 0)
  1882.       return;
  1883.  
  1884.     aSelection.type        = new Array(aSelection.length);
  1885.     aSelection.isContainer = new Array(aSelection.length);
  1886.     aSelection.containsPTF = false;
  1887.     aSelection.containsImmutable = false;
  1888.     var index, item, coopitem, parent, type, ptype, protocol, isContainer, isImmutable;
  1889.     for (var i=0; i<aSelection.length; ++i) {
  1890.       item        = aSelection.item[i];
  1891.       coopitem    = faves_coop.get_from_resource(item);    
  1892.       parent      = aSelection.parent[i];
  1893.       type        = BookmarksUtils.resolveType(item);
  1894.       protocol    = item.Value.split(":")[0];
  1895.       isContainer = (item && RDFCU.IsContainer(BMDS, item)) ||
  1896.                     protocol == "find" || protocol == "file";
  1897.       isImmutable = false;
  1898.       if (item.Value == gFL_NS+"FoldersRoot") {
  1899.         isImmutable = true;
  1900.       }
  1901.       else if (type != "Bookmark" && type != "BookmarkSeparator" && 
  1902.                type != "Folder"   && type != "PersonalToolbarFolder" &&
  1903.                type != "Livemark" && type != "Account")
  1904.         isImmutable = true;
  1905.       else if (parent) {
  1906.         var ptype = BookmarksUtils.resolveType(parent);
  1907.         if (ptype == "Livemark")
  1908.           isImmutable = true;
  1909.         var parentProtocol = parent.Value.split(":")[0];
  1910.         if (parentProtocol == "find" || parentProtocol == "file")
  1911.           aSelection.parent[i] = null;
  1912.       }
  1913.       if (isImmutable)
  1914.         aSelection.containsImmutable = true;
  1915.  
  1916.       aSelection.type       [i] = type;
  1917.       aSelection.isContainer[i] = isContainer;
  1918.     }
  1919.     if (this.isContainerChildOrSelf(BMSVC.getBookmarksToolbarFolder(), aSelection))
  1920.       aSelection.containsPTF = true;
  1921.  
  1922.     // dumpObj(aSelection);  
  1923.   },
  1924.  
  1925.   isSelectionValidForInsertion: function (aSelection, aTarget)
  1926.   {
  1927.     return BookmarksUtils.isValidTargetContainer(aTarget.parent, aSelection)
  1928.   },
  1929.  
  1930.   isSelectionValidForDeletion: function (aSelection)
  1931.   {
  1932.     dump('isSelectionValidForDeletion called \n');
  1933.     return !aSelection.containsImmutable && !aSelection.containsPTF;
  1934.   },
  1935.  
  1936.   /////////////////////////////////////////////////////////////////////////////
  1937.   // Returns true is aContainer is a member or a child of the selection
  1938.   isContainerChildOrSelf: function (aContainer, aSelection)
  1939.   {
  1940.     var folder = aContainer;
  1941.     do {
  1942.       for (var i=0; i<aSelection.length; ++i) {
  1943.         if (aSelection.isContainer[i] && aSelection.item[i].Value == folder.Value)
  1944.           return true;
  1945.       }
  1946.       folder = BMSVC.getParent(folder);
  1947.       if (!folder)
  1948.         return false; // sanity check
  1949.     } while (folder.Value != gFL_NS+"FoldersRoot")
  1950.     return false;
  1951.   },
  1952.  
  1953.   foundLocalBookmarkParent: function(aURN)
  1954.   {
  1955.     var coopObj = faves_coop.get(aURN);
  1956.     if(coopObj)
  1957.     {
  1958.       var parents = coopObj.getParents();
  1959.       for(var i=0; i<parents.length; i++)
  1960.       {
  1961.         if(this.isOnlineBookmarkRoot(parents[i]))
  1962.           return false;
  1963.       }
  1964.     }
  1965.     return true;
  1966.   },
  1967.   
  1968.   isOnlineBookmarkRoot: function(parent)
  1969.   {
  1970.     
  1971.     if(parent == null)
  1972.     {
  1973.       return false;
  1974.     }
  1975.     else if( parent.id() == gFL_NS+"OnlineBookmarksRoot")
  1976.     {
  1977.       return true;
  1978.     }else
  1979.     {
  1980.       return this.isOnlineBookmarkRoot(parent.getParent())
  1981.     }
  1982.   },
  1983.   /////////////////////////////////////////////////////////////////////////////
  1984.   // Returns true if aSelection can be inserted in aFolder
  1985.   isValidTargetContainer: function (aFolder, aSelection)
  1986.   {
  1987.     if (!aFolder)
  1988.       return false;
  1989.     if (aFolder.Value == gFL_NS+"FoldersRoot")
  1990.       return true;
  1991.     if (aFolder.Value == gFL_NS+"BookmarksRoot")
  1992.       return true;
  1993.     if(aFolder.Value == gFL_NS+"OnlineBookmarksRoot")
  1994.     {
  1995.      return false;
  1996.     }
  1997.     if(!this.foundLocalBookmarkParent(aFolder.Value))
  1998.     {
  1999.       return false;
  2000.     }
  2001.     // don't insert items in an invalid container
  2002.     // 'file:' and 'find:' items have a 'Bookmark' type
  2003.     var type = BookmarksUtils.resolveType(aFolder);
  2004.     if (type != "Folder" && type != "PersonalToolbarFolder")
  2005.       return false;
  2006.  
  2007.     // bail if we just check the container
  2008.     if (!aSelection)
  2009.       return true;
  2010.  
  2011.     // check that the selected folder is not the selected item nor its child
  2012.     if (this.isContainerChildOrSelf(aFolder, aSelection))
  2013.       return false;
  2014.  
  2015.     return true;
  2016.   },
  2017.  
  2018.   /////////////////////////////////////////////////////////////////////////////
  2019.   removeAndCheckSelection: function (aAction, aSelection)
  2020.   {
  2021.     //dump("CDC: removeAndCheckSelection()\n");
  2022.     var isValid = BookmarksUtils.isSelectionValidForDeletion(aSelection);
  2023.     if (!isValid) {
  2024.       SOUND.beep();
  2025.       return false;
  2026.     }
  2027.     this.removeSelection(aAction, aSelection);
  2028.     BookmarksUtils.flushDataSource();
  2029.     BookmarksUtils.refreshSearch();
  2030.     return true;
  2031.   },
  2032.  
  2033.   getflockUtilsObject:function()
  2034.   {
  2035.     return Components.classes['@flock.com/singleton;1']
  2036.                            .getService(Components.interfaces.flockISingleton)
  2037.                            .getSingleton('chrome://browser/content/bookmarks/flockBookmarksHelper.js')
  2038.                            .wrappedJSObject;
  2039.   },
  2040.   removeSelection: function (aAction, aSelection)
  2041.   {
  2042.     //dump("CDC: removeSelection()\n");
  2043.     if (aSelection.length > 1)
  2044.       gBkmkTxnSvc.startBatch();
  2045.     if (aSelection.length > kBATCH_LIMIT && aAction != "move")
  2046.       BMDS.beginUpdateBatch();
  2047.  
  2048.     for (var i = 0; i < aSelection.length; ++i) {
  2049.       // try to put back aSelection.parent[i] if it's null, so we can delete after searching
  2050.       if (aSelection.parent[i] == null) {
  2051.           aSelection.parent[i] = BMDS.getParent(aSelection.item[i]);
  2052.         dump("The parent was null: set to the first parent we get\n");
  2053.       }
  2054.  
  2055.       if (aSelection.parent[i]) {
  2056.         RDFC.Init(BMDS, aSelection.parent[i]);
  2057.  
  2058.         // save the selection property into array that is used later in
  2059.         // when performing the REMOVE transaction
  2060.         // (if the selection is folder save all childs property)
  2061.         var propArray;
  2062.         if (aAction != "move") {
  2063.             propArray = new Array(gBmProperties.length);
  2064.             var aType = BookmarksUtils.resolveType(aSelection.item[i]);            
  2065.             if (aType != "Livemark") {// don't change livemark properties
  2066.                for (var j = 0; j < gBmProperties.length; ++j) {
  2067.                   var oldValue = BMDS.GetTarget(aSelection.item[i], gBmProperties[j], true);
  2068.                   if (oldValue) {
  2069.                       propArray[j] = BookmarksUtils.getNodeInterface(oldValue);
  2070.                   }
  2071.                }
  2072.             }
  2073.             if (aType == "Folder" || aType == "Livemark")
  2074.                 BookmarksUtils.getAllChildren(aSelection.item[i], propArray);
  2075.         }
  2076.  
  2077.         var proplength = propArray ? propArray.length : 0;
  2078.         gBkmkTxnSvc.createAndCommitTxn(gBkmkTxnSvc.REMOVE, aAction, 
  2079.                                        aSelection.item[i], 
  2080.                                        RDFC.IndexOf(aSelection.item[i]),
  2081.                                        aSelection.parent[i], 
  2082.                                        proplength, propArray);
  2083.       }
  2084.     }
  2085.     if (aSelection.length > 1)
  2086.       gBkmkTxnSvc.endBatch();
  2087.     if (aSelection.length > kBATCH_LIMIT && aAction != "move")
  2088.       BMDS.endUpdateBatch();
  2089.     return true;
  2090.   },
  2091.  
  2092.   //  this recursive function return array of all childrens properties for given folder
  2093.   getAllChildren: function (folder, propArray)
  2094.   {
  2095.     var container = Components.classes[kRDFCContractID].createInstance(kRDFCIID);
  2096.     container.Init(BMDS, folder);
  2097.     var children = container.GetElements();
  2098.     while (children.hasMoreElements()) {
  2099.       var child = children.getNext();
  2100.       if (child instanceof Components.interfaces.nsIRDFResource) {
  2101.          var aType = BookmarksUtils.resolveType(child);
  2102.          var childResource = child.QueryInterface(kRDFRSCIID);
  2103.          var props = new Array(gBmProperties.length);
  2104.          // don't change livemark properties
  2105.          if (aType != "Livemark") {
  2106.             for (var j = 0; j < gBmProperties.length; ++j) {
  2107.                var oldValue = BMDS.GetTarget(childResource, gBmProperties[j], true);
  2108.                if (oldValue) {
  2109.                   props[j] = BookmarksUtils.getNodeInterface(oldValue);
  2110.                }
  2111.             }
  2112.          }
  2113.          propArray.push(props);
  2114.          if (aType == "Folder" || aType == "Livemark") {
  2115.             BookmarksUtils.getAllChildren(child, propArray);
  2116.          }
  2117.       }
  2118.     }
  2119.   },
  2120.  
  2121.   // if we are in search mode i.e. "find:" is in ref attribute we refresh the Search
  2122.   refreshSearch: function ()
  2123.   {
  2124.    var bmTree, bmView = document.getElementById("bookmarks-view");
  2125.    if (bmView) bmTree = bmView.tree;
  2126.    else return;
  2127.    var aRef = bmTree.getAttribute("ref");
  2128.    var aProtocol = aRef.split(":")[0];
  2129.    if (aProtocol == "find"){
  2130.       bmTree.setAttribute("ref", "");
  2131.       bmTree.setAttribute("ref", aRef);
  2132.    }
  2133.   },
  2134.         
  2135.   insertAndCheckSelection: function (aAction, aSelection, aTarget, aTargetIndex)
  2136.   {
  2137.     var isValid = BookmarksUtils.isSelectionValidForInsertion(aSelection, aTarget);
  2138.     if (!isValid) {
  2139.       SOUND.beep();
  2140.       return false;
  2141.     }
  2142.     this.insertSelection(aAction, aSelection, aTarget, aTargetIndex);
  2143.     BookmarksUtils.flushDataSource();
  2144.     BookmarksUtils.refreshSearch();
  2145.     return true;
  2146.   },
  2147.  
  2148.   insertSelection: function (aAction, aSelection, aTarget, aTargetIndex)
  2149.   {
  2150.     var inserted = 0;
  2151.     var item, removedProps;
  2152.     var index = aTarget.index;
  2153.     var brokenIndex = aTarget.index;
  2154.  
  2155.     if (aSelection.length > 1)
  2156.       gBkmkTxnSvc.startBatch();
  2157.     if (aSelection.length > kBATCH_LIMIT && aAction != "move")
  2158.       BMDS.beginUpdateBatch();
  2159.  
  2160.     for (var i=0; i<aSelection.length; ++i) {
  2161.       var rSource = aSelection.item[i];
  2162.         if (BMSVC.isBookmarkedResource(rSource) && aAction == "paste")
  2163.           rSource = BMSVC.cloneResource(rSource);
  2164.       item = rSource;
  2165.       // we only have aSelection.prop if insertSelection call by paste action we don't use it for move
  2166.       removedProps = aSelection.prop ? aSelection.prop[i] : null;
  2167.       // Broken Insert Code attempts to always insert items in the
  2168.       // right place (i.e. after the selected item).  However, because
  2169.       // of RDF Container suckyness, this code gets very confused, due
  2170.       // to rdf container indexes not matching up to number of items,
  2171.       // and because we can't trust GetCount to return a real count.
  2172.       // The -1 is there to handle inserting into the persontal toolbar
  2173.       // folder via right-click on the PTF.
  2174.       if (aTarget.index == -1) {
  2175.         index = -1;
  2176.       } else {
  2177. //@line 2222 "/cygdrive/K/tinderbuild/src/flock/mozilla/browser/components/bookmarks/content/bookmarks.js"
  2178.       index = brokenIndex++;
  2179. //@line 2224 "/cygdrive/K/tinderbuild/src/flock/mozilla/browser/components/bookmarks/content/bookmarks.js"
  2180.       }
  2181.       var proplength = removedProps ? removedProps.length : 0;
  2182.       
  2183.       // ERWN: Having the same favorite twice in a folder is causing problems,
  2184.       // so we don't allow it
  2185.       RDFC.Init(BMDS, aTarget.parent);
  2186.       if (RDFC.IndexOf(item) == -1) {
  2187.         gBkmkTxnSvc.createAndCommitTxn(gBkmkTxnSvc.INSERT, aAction, item, index,
  2188.                                        aTarget.parent, proplength, removedProps);
  2189.         inserted++;
  2190.       }else {
  2191.          var coopitem = faves_coop.get(item.Value);
  2192.           if(coopitem.rdftype && coopitem.rdftype.indexOf("BookmarkSeparator") > -1)
  2193.           {
  2194.             BookmarksCommand.createNewSeparator(aTarget);
  2195.           }
  2196.       }
  2197.     }
  2198.     if (inserted > 1)
  2199.       gBkmkTxnSvc.endBatch();
  2200.     if (inserted > kBATCH_LIMIT && aAction != "move")
  2201.       BMDS.endUpdateBatch();
  2202.   },
  2203.   
  2204.   moveAndCheckSelection: function (aAction, aSelection, aTarget)
  2205.   {
  2206.     var isValid = BookmarksUtils.isSelectionValidForDeletion(aSelection) &&
  2207.                   BookmarksUtils.isSelectionValidForInsertion(aSelection, aTarget);
  2208.     if (!isValid) {
  2209.       SOUND.beep();
  2210.       return false;
  2211.     }
  2212.     this.moveSelection(aAction, aSelection, aTarget);
  2213.     BookmarksUtils.flushDataSource();
  2214.     return true;
  2215.   },
  2216.  
  2217.   moveSelection: function (aAction, aSelection, aTarget)
  2218.   {
  2219.     if (aSelection.length > kBATCH_LIMIT)
  2220.       BMDS.beginUpdateBatch();
  2221.  
  2222.     gBkmkTxnSvc.startBatch();
  2223.     BookmarksUtils.removeSelection("move", aSelection);
  2224.     BookmarksUtils.insertSelection("move", aSelection, aTarget);
  2225.     gBkmkTxnSvc.endBatch();
  2226.     if (aSelection.length > kBATCH_LIMIT)
  2227.       BMDS.endUpdateBatch();
  2228.   }, 
  2229.  
  2230.   // returns true if this selection should be copied instead of moved,
  2231.   // if a move was originally requested
  2232.   shouldCopySelection: function (aAction, aSelection)
  2233.   {
  2234.     for (var i = 0; i < aSelection.length; i++) {
  2235.       var parentType = BookmarksUtils.resolveType(aSelection.parent[i]);
  2236.       if (aSelection.type[i] == "ImmutableBookmark" ||
  2237.           aSelection.type[i] == "ImmutableFolder" ||
  2238.           aSelection.parent[i] == null || 
  2239.           (aSelection.type[i] == "Bookmark" && parentType == "Livemark"))
  2240.       {
  2241.         return true;            // if any of these are found
  2242.       }
  2243.     }
  2244.  
  2245.     return false;
  2246.   },
  2247.  
  2248.   getXferDataFromSelection: function (aSelection)
  2249.   {
  2250.     if (aSelection.length == 0)
  2251.       return null;
  2252.     var dataSet = new TransferDataSet();
  2253.     var data, item, itemUrl, itemName, parent, name;
  2254.     for (var i=0; i<aSelection.length; ++i) {
  2255.       data     = new TransferData();
  2256.       item     = aSelection.item[i].Value;
  2257.       itemUrl  = this.getProperty(item, gNC_NS+"URL");
  2258.       itemName = this.getProperty(item, gNC_NS+"Name");
  2259.       parent   = aSelection.parent[i].Value;
  2260.       data.addDataForFlavour("moz/rdfitem",    item+"\n"+(parent?parent:""));
  2261.       data.addDataForFlavour("text/x-moz-url", itemUrl+"\n"+itemName);
  2262.       data.addDataForFlavour("text/html",      "<A HREF='"+itemUrl+"'>"+itemName+"</A>");
  2263.       data.addDataForFlavour("text/unicode",   itemUrl);
  2264.       dataSet.push(data);
  2265.     }
  2266.     return dataSet;
  2267.   },
  2268.  
  2269.   getSelectionFromXferData: function (aDragSession)
  2270.   {
  2271.     var selection    = {};
  2272.     selection.item   = [];
  2273.     selection.parent = [];
  2274.     var trans = Components.classes["@mozilla.org/widget/transferable;1"]
  2275.                           .createInstance(Components.interfaces.nsITransferable);
  2276.     trans.addDataFlavor("moz/rdfitem");
  2277.     trans.addDataFlavor("text/x-moz-url");
  2278.     trans.addDataFlavor("text/unicode");
  2279.     var uri, extra, rSource, rParent, parent;
  2280.     for (var i = 0; i < aDragSession.numDropItems; ++i) {
  2281.       var bestFlavour = {}, dataObj = {}, len = {};
  2282.       aDragSession.getData(trans, i);
  2283.       trans.getAnyTransferData(bestFlavour, dataObj, len);
  2284.       dataObj = dataObj.value.QueryInterface(Components.interfaces.nsISupportsString);
  2285.       if (!dataObj)
  2286.         continue;
  2287.       dataObj = dataObj.data.substring(0, len.value).split("\n");
  2288.       uri     = dataObj[0];
  2289.       if (dataObj.length > 1 && dataObj[1] != "")
  2290.         extra = dataObj[1];
  2291.       else
  2292.         extra = null;
  2293.       switch (bestFlavour.value) {
  2294.       case "moz/rdfitem":
  2295.         rSource = RDF.GetResource(uri);
  2296.         parent  = extra;
  2297.         break;
  2298.       case "text/x-moz-url":
  2299.       case "text/unicode":
  2300.         rSource = BookmarksUtils.createBookmark(null, uri, null, extra, null);
  2301.         parent = null;
  2302.         break;
  2303.       }
  2304.       selection.item.push(rSource);
  2305.       if (parent)
  2306.         rParent = RDF.GetResource(parent);
  2307.       else
  2308.         rParent = null;
  2309.       selection.parent.push(rParent);
  2310.     }
  2311.     selection.length = selection.item.length;
  2312.     BookmarksUtils.checkSelection(selection);
  2313.     return selection;
  2314.   },
  2315.  
  2316.   getTargetFromFolder: function(aResource)
  2317.   {
  2318.     var index = parseInt(this.getProperty(aResource, gRDF_NS+"nextVal"));
  2319.     if (isNaN(index))
  2320.       return {parent: null, index: -1};
  2321.     else
  2322.       return {parent: aResource, index: index};
  2323.   },
  2324.  
  2325.   getSelectionFromResource: function (aItem, aParent)
  2326.   {
  2327.     var selection    = {};
  2328.     selection.length = 1;
  2329.     selection.item   = [aItem  ];
  2330.     selection.parent = [aParent];
  2331.     this.checkSelection(selection);
  2332.     return selection;
  2333.   },
  2334.  
  2335.   createBookmark: function (aName, aURL, aCharSet, aDefaultName)
  2336.   {
  2337.     if (!aName) {
  2338.       // look up in the history ds to retrieve the name
  2339.       var rSource = RDF.GetResource(aURL);
  2340.       var HISTDS  = RDF.GetDataSource("rdf:history");
  2341.       var nameArc = RDF.GetResource(gNC_NS+"Name");
  2342.       var rName   = HISTDS.GetTarget(rSource, nameArc, true);
  2343.       aName       = rName ? rName.QueryInterface(kRDFLITIID).Value : aDefaultName;
  2344.       if (!aName)
  2345.         aName = aURL;
  2346.     }
  2347.     if (!aCharSet) {
  2348.       var fw = document.commandDispatcher.focusedWindow;
  2349.       if (fw)
  2350.         aCharSet = fw.document.characterSet;
  2351.     }
  2352.     return BMSVC.createBookmark(aName, aURL, null, null, aCharSet, null);
  2353.   },
  2354.  
  2355.   createLivemark: function (aName, aURL, aFeedURL, aDefaultName)
  2356.   {
  2357.     if (!aName) {
  2358.       // look up in the history ds to retrieve the name
  2359.       var rSource = RDF.GetResource(aURL);
  2360.       var HISTDS  = RDF.GetDataSource("rdf:history");
  2361.       var nameArc = RDF.GetResource(gNC_NS+"Name");
  2362.       var rName   = HISTDS.GetTarget(rSource, nameArc, true);
  2363.       aName       = rName ? rName.QueryInterface(kRDFLITIID).Value : aDefaultName;
  2364.       if (!aName)
  2365.         aName = aURL;
  2366.     }
  2367.     return BMSVC.createLivemark(aName, aURL, aFeedURL, null);
  2368.   },
  2369.  
  2370.   flushDataSource: function ()
  2371.   {
  2372.     var remoteDS = BMDS.QueryInterface(Components.interfaces.nsIRDFRemoteDataSource);
  2373.     setTimeout(function () {remoteDS.Flush()}, 100);
  2374.   },
  2375.  
  2376.   addBookmark: function (aURL, aTitle, aCharset, aIsWebPanel, aDescription)
  2377.   {
  2378.     if(this._observerService == null)
  2379.     {
  2380.       this._observerService = Components.classes["@mozilla.org/observer-service;1"]
  2381.                                 .getService(Components.interfaces.nsIObserverService);
  2382.     }
  2383.      var dArgs = new String(aTitle+';'+aURL+';'+aCharset+';'+ aIsWebPanel+';'+aDescription);
  2384.      this._observerService.notifyObservers(null, 'starCurrent', dArgs);
  2385.   },
  2386.  
  2387.   addBookmarkForAllTabs: function (aTabBrowser) {
  2388.     var tabsInfo = [];
  2389.  
  2390.     const activeBrowser = aTabBrowser.selectedBrowser;
  2391.     const browsers = aTabBrowser.browsers;
  2392.     for (var i = 0; i < browsers.length; ++i) {
  2393.       var webNav = browsers[i].webNavigation;
  2394.       var url = webNav.currentURI.spec;
  2395.       var name = "";
  2396.       var charSet, description;
  2397.       try {
  2398.         var doc = webNav.document;
  2399.         name = doc.title || url;
  2400.         charSet = doc.characterSet;
  2401.         description = BookmarksUtils.getDescriptionFromDocument(doc);
  2402.       } catch (e) {
  2403.         name = url;
  2404.       }
  2405.       tabsInfo[i] = { name: name, url: url, charset: charSet, description: description };
  2406.       if (browsers[i] == activeBrowser)
  2407.         currentTabInfo = tabsInfo[i];
  2408.     }
  2409.  
  2410.     var dArgs = {
  2411.       name: gNavigatorBundle.getString("bookmarkAllTabsDefault"),
  2412.       url: "",
  2413.       charset: null,
  2414.       bWebPanel: false,
  2415.       bBookmarkAllTabs: true,
  2416.       objGroup: tabsInfo
  2417.     };
  2418.     
  2419.     openDialog("chrome://browser/content/bookmarks/addBookmark2.xul", "", "centerscreen,chrome,dialog,resizable,modal", dArgs)
  2420.   },
  2421.  
  2422.   addLivemark: function (aURL, aFeedURL, aTitle, aDescription)
  2423.   {
  2424.     var dArgs = {
  2425.       name: aTitle,
  2426.       url: aURL,
  2427.       bWebPanel: false,
  2428.       feedURL: aFeedURL,
  2429.       description: aDescription
  2430.     };
  2431.     try {
  2432.       var toolbarFolderURI = BMDS.getBookmarksToolbarFolder().Value;
  2433.       dArgs.folderURI = toolbarFolderURI;
  2434.     }
  2435.     catch (e) { 
  2436.     }
  2437.     openDialog("chrome://browser/content/bookmarks/addBookmark2.xul", "",
  2438.                ADD_BM_DIALOG_FEATURES, dArgs);
  2439.   },
  2440.  
  2441.   getDescriptionFromDocument: function (aDocument) {
  2442.     var metaElements = aDocument.getElementsByTagName('META');
  2443.     for (var m = 0; m < metaElements.length; m++) {
  2444.       if (metaElements[m].name.toLowerCase() == 'description' || metaElements[m].httpEquiv.toLowerCase() == 'description')
  2445.         return metaElements[m].content;
  2446.     }
  2447.     return '';
  2448.   },
  2449.  
  2450.   loadFavIcon: function (aURL, aFavIconURL) {
  2451.     if (!RDF || !BMSVC)
  2452.       return;
  2453.  
  2454.     var urlLiteral = RDF.GetLiteral(aURL);
  2455.     // don't do anything if this URI isn't bookmarked
  2456.     var bmResources = BMSVC.GetSources(RDF.GetResource(gNC_NS+"URL"), urlLiteral, true);
  2457.     var toUpdate = 0;
  2458.  
  2459.     while (bmResources.hasMoreElements()) {
  2460.       var bmResource = bmResources.getNext();
  2461.  
  2462.       // don't flag this as needing update if it already has a data: icon url set
  2463.       var oldIcon = BMDS.GetTarget(bmResource, RDF.GetResource(gNC_NS+"Icon"), true);
  2464.       if (oldIcon && (oldIcon.QueryInterface(kRDFLITIID).Value.substring(0,5) == "data:"))
  2465.         continue;
  2466.  
  2467.       toUpdate++;
  2468.     }
  2469.  
  2470.     if (toUpdate == 0)
  2471.       return;
  2472.  
  2473.     var chan = IOSVC.newChannel(aFavIconURL, null, null);
  2474.     var listener = new bookmarksFavIconLoadListener (aURL, aFavIconURL, chan);
  2475.     chan.notificationCallbacks = listener;
  2476.     chan.asyncOpen(listener, null);
  2477.   }
  2478. }
  2479.  
  2480. var BookmarkEditMenuTxnListener =
  2481. {
  2482.   didDo: function (aTxmgr, aTxn)
  2483.   {
  2484.     this.updateMenuItem(aTxmgr, aTxn);
  2485.   },
  2486.  
  2487.   didUndo: function (aTxmgr, aTxn)
  2488.   {
  2489.     this.updateMenuItem(aTxmgr, aTxn);
  2490.   },
  2491.  
  2492.   didRedo: function (aTxmgr, aTxn)
  2493.   {
  2494.     this.updateMenuItem(aTxmgr, aTxn);
  2495.   },
  2496.  
  2497.   didMerge       : function (aTxmgr, aTxn) {},
  2498.   didBeginBatch  : function (aTxmgr, aTxn) {},
  2499.   didEndBatch    : function (aTxmgr, aTxn) {
  2500.     this.updateMenuItem(aTxmgr, aTxn);
  2501.   },
  2502.   willDo         : function (aTxmgr, aTxn) {},
  2503.   willUndo       : function (aTxmgr, aTxn) {},
  2504.   willRedo       : function (aTxmgr, aTxn) {},
  2505.   willMerge      : function (aTxmgr, aTxn) {},
  2506.   willBeginBatch : function (aTxmgr, aTxn) {},
  2507.   willEndBatch   : function (aTxmgr, aTxn) {},
  2508.  
  2509.   updateMenuItem: function bkmkMenuListenerUpdate(aTxmgr, aTxn) {
  2510.     var node, transactionNumber, transactionList, transactionLabel, action, item;
  2511.     node = document.getElementById("cmd_undo");
  2512.     transactionNumber = aTxmgr.numberOfUndoItems;
  2513.     dump("N UNDO: "+transactionNumber+"\n");
  2514.     if (transactionNumber == 0) {
  2515.       transactionLabel = BookmarksUtils.getLocaleString("cmd_bm_undo");
  2516.     } else {
  2517.       transactionList  = aTxmgr.getUndoList();
  2518.       if (!transactionList.itemIsBatch(transactionNumber-1)) {
  2519.         item = transactionList.getItem(transactionNumber-1);
  2520.         action = item.wrappedJSObject.action;
  2521.       } else {
  2522.         var childList = transactionList.getChildListForItem(transactionNumber-1);
  2523.         item = childList.getItem(0);
  2524.         action = item.wrappedJSObject.action;
  2525.       }
  2526.       transactionLabel = BookmarksUtils.getLocaleString("cmd_bm_"+action+"_undo");
  2527.     }
  2528.     node.setAttribute("label", transactionLabel);
  2529.       
  2530.     node = document.getElementById("cmd_redo");
  2531.     transactionNumber = aTxmgr.numberOfRedoItems;
  2532.     dump("N REDO: "+transactionNumber+"\n");
  2533.     if (transactionNumber == 0) {
  2534.       transactionLabel = BookmarksUtils.getLocaleString("cmd_bm_redo");
  2535.     } else {
  2536.       transactionList  = aTxmgr.getRedoList();
  2537.       if (!transactionList.itemIsBatch(transactionNumber-1)) {
  2538.         item = transactionList.getItem(transactionNumber-1);
  2539.         action = item.wrappedJSObject.action;
  2540.       } else {
  2541.         var childList = transactionList.getChildListForItem(transactionNumber-1);
  2542.         item = childList.getItem(0);
  2543.         action = item.wrappedJSObject.action;
  2544.       }
  2545.       transactionLabel = BookmarksUtils.getLocaleString("cmd_bm_"+action+"_redo");
  2546.     }
  2547.     node.setAttribute("label", transactionLabel);
  2548.   }
  2549. }
  2550.  
  2551. // favicon loaders
  2552.  
  2553. function bookmarksFavIconLoadListener(uri, faviconurl, channel) {
  2554.   this.mURI = uri;
  2555.   this.mFavIconURL = faviconurl;
  2556.   this.mCountRead = 0;
  2557.   this.mChannel = channel;
  2558. }
  2559.  
  2560. bookmarksFavIconLoadListener.prototype = {
  2561.   mURI : null,
  2562.   mFavIconURL : null,
  2563.   mCountRead : null,
  2564.   mChannel : null,
  2565.   mBytes : Array(),
  2566.   mStream : null,
  2567.  
  2568.   QueryInterface: function (iid) {
  2569.     if (!iid.equals(Components.interfaces.nsISupports) &&
  2570.         !iid.equals(Components.interfaces.nsIInterfaceRequestor) &&
  2571.         !iid.equals(Components.interfaces.nsIRequestObserver) &&
  2572.         !iid.equals(Components.interfaces.nsIChannelEventSink) &&
  2573.         !iid.equals(Components.interfaces.nsIProgressEventSink) && // see below
  2574.         !iid.equals(Components.interfaces.nsIStreamListener)) {
  2575.       throw Components.results.NS_ERROR_NO_INTERFACE;
  2576.     }
  2577.     return this;
  2578.   },
  2579.  
  2580.   // nsIInterfaceRequestor
  2581.   getInterface: function (iid) {
  2582.     try {
  2583.       return this.QueryInterface(iid);
  2584.     } catch (e) {
  2585.       throw Components.results.NS_NOINTERFACE;
  2586.     }
  2587.   },
  2588.  
  2589.   // nsIRequestObserver
  2590.   onStartRequest : function (aRequest, aContext) {
  2591.     this.mStream = Components.classes['@mozilla.org/binaryinputstream;1'].createInstance(Components.interfaces.nsIBinaryInputStream);
  2592.   },
  2593.  
  2594.   onStopRequest : function (aRequest, aContext, aStatusCode) {
  2595.     var httpChannel = this.mChannel.QueryInterface(Components.interfaces.nsIHttpChannel);
  2596.     if ((httpChannel && httpChannel.requestSucceeded) &&
  2597.         Components.isSuccessCode(aStatusCode) &&
  2598.         this.mCountRead > 0)
  2599.     {
  2600.       var dataurl;
  2601.       // XXX - arbitrary size beyond which we won't store a favicon.  This is /extremely/
  2602.       // generous, and is probably too high.
  2603.       if (this.mCountRead > 16384) {
  2604.         dataurl = "data:";      // hack meaning "pretend this doesn't exist"
  2605.       } else {
  2606.         // get us a mime type for this
  2607.         var mimeType = null;
  2608.  
  2609.         const nsICategoryManager = Components.interfaces.nsICategoryManager;
  2610.         const nsIContentSniffer = Components.interfaces.nsIContentSniffer;
  2611.  
  2612.         var catMgr = Components.classes["@mozilla.org/categorymanager;1"].getService(nsICategoryManager);
  2613.         var sniffers = catMgr.enumerateCategory("content-sniffing-services");
  2614.         while (mimeType == null && sniffers.hasMoreElements()) {
  2615.           var snifferCID = sniffers.getNext().QueryInterface(Components.interfaces.nsISupportsCString).toString();
  2616.           var sniffer = Components.classes[snifferCID].getService(nsIContentSniffer);
  2617.  
  2618.           try {
  2619.             mimeType = sniffer.getMIMETypeFromContent (this.mBytes, this.mCountRead);
  2620.           } catch (e) {
  2621.             mimeType = null;
  2622.             // ignore
  2623.           }
  2624.         }
  2625.       }
  2626.  
  2627.       if (mimeType == null) {
  2628.         BMSVC.updateBookmarkIcon(this.mURI, null, null, 0);
  2629.       } else {
  2630.         BMSVC.updateBookmarkIcon(this.mURI, mimeType, this.mBytes, this.mCountRead);
  2631.       }
  2632.     }
  2633.  
  2634.     this.mChannel = null;
  2635.   },
  2636.  
  2637.   // nsIStreamObserver
  2638.   onDataAvailable : function (aRequest, aContext, aInputStream, aOffset, aCount) {
  2639.     // we could get a different aInputStream, so we don't save this;
  2640.     // it's unlikely we'll get more than one onDataAvailable for a
  2641.     // favicon anyway
  2642.     this.mStream.setInputStream(aInputStream);
  2643.  
  2644.     var chunk = this.mStream.readByteArray(aCount);
  2645.     this.mBytes = this.mBytes.concat(chunk);
  2646.     this.mCountRead += aCount;
  2647.   },
  2648.  
  2649.   // nsIChannelEventSink
  2650.   onChannelRedirect : function (aOldChannel, aNewChannel, aFlags) {
  2651.     this.mChannel = aNewChannel;
  2652.   },
  2653.  
  2654.   // nsIProgressEventSink: the only reason we support
  2655.   // nsIProgressEventSink is to shut up a whole slew of xpconnect
  2656.   // warnings in debug builds.  (see bug #253127)
  2657.   onProgress : function (aRequest, aContext, aProgress, aProgressMax) { },
  2658.   onStatus : function (aRequest, aContext, aStatus, aStatusArg) { }
  2659. }
  2660.  
  2661. //@line 2812 "/cygdrive/K/tinderbuild/src/flock/mozilla/browser/components/bookmarks/content/bookmarks.js"
  2662.  
  2663.